본문 바로가기

카테고리 없음

자바의 정석 7장 주요 내용 정리 (7-1)

상속

◆상속의 장점◆

● 상속을 통해서 클래스를 작성하면 적은 양의 코드로 새로운 클래스를 작성가능

● 코드의 추가 및 변경이 매우 용이하다

● 코드의 재사용성을 높이고 중복을 제거, 유지보수 향상, 생산성 향상

 

class Child extends Parent{ //자바 상속하는 키워드 extends
	//.....
}

 

조상 클래스 = 부모 클래스, 상위 클래스, 기반 클래스

자손 클래스 = 자식 클래스, 하위 클래스, 파생된 클래스

상속은 IS A 관계

 

 

 

생성자와 초기화 블럭은 상속되지 않는다. 멤버만 상속된다.

자손 클래스의 멤버 개수는 조상 클래스보다 항상 같거나 많다.

 

class Tv {
	boolean power;
    int channel;
    
    void power(){ power = !power;}
    void channelUp() {++channel;}
    void channelDown(){--channel;}
}

class CaptionTv extends Tv{
	boolean caption;
    void displayCaption(String text){
    	if(caption){
        	System.out.println(text);
        }
    }
}

class CaptionTvTest{

	public static void main(String args[]){
    
    	CaptionTv ctv = new CaptionTv();
        ctv.channel =10;//조상 클래스로 부터 상속받은 멤버
        ctv.channelUp();//조상 클래스로 부터 상속받은 멤버
        ctv.channel; //11
        
        
    }

}

 

 

 

클래스 간의 포함 관계 is a , has 코드 예시

 

 

 

class Circle{

	Point c = new Point();
    int r;
}

has a 관계 원은 점을 가지고 있다.

 

class Circle extends Point{
	int r;
}

is a 원은 점이다

 

 

 

 

Is a , has a full example of code

 

 

class DrawShape{

	public static void main(String[] args){
    	Point[] p = {
        	new Point(100, 100),
            new Point(140, 50),
            new Point(200, 100)
        };
        Triangle t = new Triangle(p);
        Circle c = new Circle(new Point(150, 150), 50);
        t.draw();
        c.draw();
    }
}


class Point{
	int x,y;
    Point(int x, int y){
    	this.x = x;
        this.y =y;
    }
    Point(){
    	this(0,0);
    }
    
    String getXY(){
    	return x + "," + y;
    }
}
class Circle extends Shape{
	Point center;
    int r;
    Circle(){
    	this(new Point(0,0), 100);
    }

	Circle(Point center, int r){
    	this.center = center;
        this.r = r;
    }
    
    
    void draw(){
    	//.. 출력문 center.x, center.y, r, color
    }
}

class Triangel extends Shape{
	Point[] p = new Point[3];
    Triangle(Point[] p){
    	this.p = p;
    
    }
    void draw(){
    	System.out.println("p1=%s, p2=%s, p3=%s,color=%s"),
        p[0].getXY(),p[1].getXY(), p[2].getXY(), color);
    
    }
    
    
    


}

 

 

class Shape{
	String color ="black";
    void draw(){
    	System.out.println("color=%s",color);
    }

}

 

 

원은 도형이다.

원은 점을 가지고 있다.

 

 

 

오버라이딩 예시 : 조상클래스에 정의된 메서드와 같이 메서드를 자손 클래스에 정의하는 것을 오버라이딩이라고 하며, 곧이어 배울 내용

 

class Shape{
	String color ="black";
    void draw(){
    	System.out.println("color=%s",color);
    }
}

class Circle extends Shape{
	void draw(){
    	System.out.println("center=%d, %d,   r=%d,color=%s",
        center.x, center.y, r, color);
    }

}

오버라이딩의 조건

▶ 자손 클래스에서 오버라이딩하는 메서드는 조상 클래스의 메서드와 "이름이 같아야 한다."

▶ 자손 클래스에서 오버라이딩하는 메서드는 조상 클래스의 메서드와"매개변수가 같아야 한다."

▶ 자손 클래스에서 오버라이딩하는 메서드는 조상 클래스의 메서드와"반환타입이 같아야 한다."

 

 

접근 제어자는 조상 클래스의 메서드보다 좁은 범위로 변경 할 수 없다.

 

◈ 조상 클래스의 메서드를 자손 클래스에서 오버라이딩할 때  ◈

▶ 접근 제어자를 조상 클래스의 메서드보다 좁은 범위로 변경할 수 없다.

▶ 예외는 조상 클래스의 메서드보다 많이 선언할 수 없다.

▶ 인스턴스메서드를 static 메서드로 또는 그 반대로 변경할 수 없다.

 

 

자바는 다중상속을 허용하지 않는다. 한 클래스를 조상으로 하고 타 클래스를 포함 시키면 포함 시킨 클래스에서 메서드와 일치하는 선언부를 가진 사용할 수 있다.

class Tv{
	boolean power;
    int channel;
    
    void power{ power = !power;}
    void channelUp(){++channel;}
    void channelDown(){--channel;}
}

class VCR{
	boolean power;
    int counter =0;
    void power() { power = !power;}
    void paly(){///.....}
	void stop(){///.....}
    void rew(){///.....}
    void ff(){///.....}
}


class TVCR extends Tv{
	VCR vcr = new VCR();//vcr 포함 시켜서 인스턴스화 후에 호출
    
    void play(){
    	vcr.play();
    }


	void stop(){
    	vcr.stop();
    }
    
    void rew(){
    	vcr.rew();
    }
    
    void ff(){
    	vcr.ff();
    }
    
    
    
}

 

 

 

super의 설명 : super는 자손 클래스에서 조상 클래스로 부터 상속받은 멤버를 참조하는데 사용되는 참조 변수이다.

멤버변수와 지역변수 이름이 같을 때 this를 붙여 구별하듯 상속받은 멤버와 자신의 멘버와 이름이 같을 때 super로 구분

 

 

class SuperTest{
	public static void main(String args[]){
    	Child c = new Child();
        c.method();
    }
}

class Parent{
	int x =10;
}


class Child extends Parent{
	void method(){
    	System.out.println("x="+x);//10
        System.out.println("this.x" + this.x);//10
        System.out.println("super.x" + super.x);//10
    }

}

 

 

 

super.x는 조상 클래스로부터 상속받은 멤버변수 x를 뜻하며, this.x는 자손 클랫에 선언된 멤버변수

 

♣sper를 이용한 오버라이딩♣

class Point{
	int x,y;
    String getLocation(){
		return "x: " +x +"y:" +y;    
    }

}



class Point3d extends Point{

	int z;
    String getLocation(){
    	return super.getLocation() + ", :" +z;
    }
}

 

this는 같은 클래스의 다른 생성자를 호출하는 데 사용되지만, super()는 조상 클래스의 새성자를 호출하는데 사용된다.

 

sper 사용시 주의할 점

class PointTest{
	public static void main(String []args){
    	Point3D p3 = new Point3D(1,2 ,3);
    
    }

}

class Point{

	int x,y;
    Point(int x, int y){
    	this.x = x;
        this.y =y;
    }
    String getLocation(){
    	return "x:" +x + "y:" + y; 
    }
}


class Point3D extends Point}{
	int z;
    Point3D(int x, int y, int z){
    //생성자 첫 줄에서 다른 생성자를 호출하지 않기 때문에 컴파일러가 super()를 삽입한다/. 
    	this.x = x;
        this.y = y;
        this.z = z;
      
    	
    }

}

 

컴파일 에러 발생함 Point3D클래스의 생성자에서 조상 클래스의 생성자 Point를 찾을 수 없음

 

 

 

solution for above code

 

 

Point3D(int x, int y, int z){

               super();

              this.x = x;

               this.y = y;

               this.z = z;

 

}

 

Point3D(int x, int y, int z){

               super(x, y);

               this.z = z;

 

}

 

 

class PointTest2{
	public static void main(String args[]){
    	Point 3D p3 = new Point3D();
        System.out.println("p3.x=",p3.x);
        System.out.println("p3.y=",p3.y);
        System.out.println("p3.z=",p3.z);
        
	}

}



class Point{

	int x=10;
    int y =20;
    Point(int x, int y){
    	super();//조상인 object 클래스의 생성자 object클래스 호출
       	this.x = x;
        this.y =y;
    }
}


class Point3D extends Point{
	int z =30;
    Point3D(){
    	this(100, 200,300);//Point3D x, y , z를 호출
    }
    Point3D(int x, int z, int z){
    	super(x,y);//Point x,y호출
        this.z =z;
    }
}

 

제어자

제어자의 종류는 크게 접근 제어자 그외로 나눈다.

접근 제어자 : public,protected, default, private

그 외 static ,final, abstract, native, transient, synchronized, volatile, strictfp

 

 

static 멤버변수 -모든 인스턴스에 공통적으로 사용되는 클래스변수가 된다.
-클래스변수는 인스턴스를 생성하지 않고도 사용 가능하다.
-클래스가 메모리에 로드될 때 생성된다.
메서드 인스턴스를 생성하지 않고도
호출이 가능한 static 메서드가 된다.
static 메서드 내에서는 인스턴스멤버들을 직접 사용할 수 없다.

 

 final 클래스 변경될 수 없는 클래스, 확장될 수 없는 클래스가 된다..
final로 지정된 클래스는 다른 클래스의 조상이 될 수 없다.
메서드 변경될 수 없는 메서드, final로 지정된 메서드는 오버라이딩을 통해 재정의 될 수 없다.
멤버변수 변수 앞 final이 붙으면 값을 변경할 수 ㅇㅂ서는 상수가 된다.
지역변수

 

 

 

final class FinalTest{//FINAIL사용시 조상이 될 수 없다.

	final int MAX_SIZE =10;//값을 변경할 수 없는 멤버변수
    final void getMaxSize(){
    	final int LV = MAX_SIZE; // 오버라이딩할 수 없는 메서드
        return MAX_SIZE;// 값을 변경할 수 없는 지역변수
    }
}

 

abstract는 미완성의 의미를 가지고 있다. 메서드의 선언부만 작성하고 실제 수행내용은 구현하지 않은 추상 메서드를 선언한는데 사용

 

 

제어자의 접근 범위

 

public > protected > default > private

접근 제어자를 이용한 캡슐화

▶ 클래스나 멤버, 주로 벰버에 접근 제어자를 사용하는 이유는 클래스의 내부에 선언된 데이터를 보호하기 위해서

▶ 내부 작업을 위해 임시로 사용되는 멤버변수나 부분작업을 처리하기 위한 메서드 등의 멤버들을 클래스 내부에 감추기 위해서

 

접근 제어자를 사용하는 이유
▶ 외부로부터 데이터를 보호하기 위해서
▶ 외부에는 불필요한, 내부적으로만 사용되는,부분을 감추기 위ㅣ해서

 

▶ 메서드에 static과 abstract를 함께 사용할 수 없다. - > static메서드는 몸통이 있는 메서드에만 사용가능
▶ 클래스에 abstract와 final을 동시에 사용할 수 없다. -> 클래스에 사용되는 final은 클래스를 확장할 수 없다는 의미 abstract는 상속을 통해서만 완성을 해야한다는 의미로 모순된다.
▶ abstract 메서드의 접근 제어자가 private일 수 없다. -> 왜냐하면 자손에서 구현해야 하기 때문에
▶ 메서드에 private과 final을 같이 사용할 필요는 없다