JAVA/java 이론

[자바JAVA]상속/포함관계

자바칩 프라푸치노 2020. 10. 18. 13:15

이 포스팅은 아래의 내용이 포함되어있습니다.

1. 상속

2. 포함

3. 상속이냐 포함이냐 결정하기

4. 단일상속

5. Object클래스

6.예제 

 

1. 상속

- 기존의 클래스를 사용하여 새로운 클래스를 만드는 것

- 자손은 조상의 멤버를 모두 상속받는다(생성자, 초기화 블럭 제외)

- 자손의 멤버개수는 조상의 멤버개수보다 많다.

 

- 공통부분은 조상에서 관리하고 개별 부분은 자손에서 관리한다.

- 조상의 변경은 자손에게 영향을 끼치지만 자손의 변경은 조상에게 영향을 끼치지 않는다.

 

상속은 이렇게 extends (확장시키다) 를 붙이고 조상클래스를 상속받는 것

 

 

2. 포함

- 한 클래스를 멤버로 다른 클래스를 선언하는 것

 

포함은 이렇게 클래스 안에 다른 클래스를 멤버로 선언하는 것

 

 

 

3. 클래스간의 관계 결정하기 : 상속이냐 포함이냐

is a 와 has a 를 가지고 문장을 만들어본다.

원은 점이다. (Circle is a point)

원은 점을 가지고 있다.  (Circle has a point)

 

원은 점을 가지고 있다가 맞기 때문에 Circle에 Point(점)이 포함된 관계이다.

 

 

여기서 Circle클래스는 Shape클래스를 상속받고 Point클래스를 포함하는 관계

 

 

4. 단일 상속

상속은 단일 상속만 허용하고, 가장 비중이 높은 클래스 하나만 상속하고 나머지는 포함관계로 표현한다.

 

5. Object클래스

조상이 없는 클래스는 기본적으로 최고 조상인 Object클래스를 상속받는다.

여기서 Tv클래스 옆에 extends를 붙이지 않아도 저절로 Object가 extends되어 컴파일된다.

 

 

(예제)

<조상클래스>

Tv클래스 

이 클래스는 조상이 Object이다.

명시적으로 붙여주지 않아도 된다.

1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
28
29
30
31
32
33
package sec01_exam상속;
//조상클래스(부모, Super클래스) 멤버 갯수: 5개
public class Tv extends Object{
 
    boolean power;
    int channel;
    
    public Tv() {
        super();//조상 클래스 (Object)의 생성자를 호출
        System.out.println("조상 클래스생성자 호출");
    }
    
    public Tv(boolean power, int channel) {
        super();//조상 클래스 (Object)의 생성자를 호출
        this.power= power;
        this.channel= channel;
        System.out.println("조상 클래스생성자 호출");
    }
    
    
    
    public void power() {
        this.power= !power;
    }
    public void channelUp() {
        ++this.channel;
    }
    
    public void channelDown() {
        --this.channel;
    }
}
 
cs

 

 

<자손클래스>

CaptionTv는 Tv를 상속받는다.

Tv클래스의 멤버들이 모두 상속된다.

개별 메서드나 변수를 선언할 수 있다.

생성자에서는 반드시 super(); (조상 클래스의 생성자)를 맨 윗줄에서 호출해주어야한다.

없어도 자동적으로 컴파일된다.

그 이유는 조상이 있어야 자손이 있기 때문이다.

 

1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
28
package sec01_exam상속;
 
public class CaptionTv  extends Tv{
 
    boolean caption;
    //조상없는 자손 없다.
    public CaptionTv() {
        super();//조상클래스(Tv)의 기본생성자 호출
        //super(true,10);
        System.out.println("자손 클래스의 생성자 호출");
    }
    
    public CaptionTv(boolean caption) {
        super();//무조건 조상 클래스의 생성자를 호출해야함
        //super(true,10);
        this.caption = caption;
        System.out.println("자손 클래스의 생성자 호출");
    }
    
    public void displayCaption(String text) {
        //1번째 호출 시에 false, 2번째 호출시에는 true
        //캡션 상태가 on(true)일때만 text를 보여준다.
        if (this.caption) {
            System.out.println(text);
        }
    }
}
 
cs

 

<실행클래스>

1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
package sec01_exam상속;
 
public class CaptionTvExample {
 
    public static void main(String[] args) {
        
        Tv tv = new Tv();
        System.out.println("----------------------");
        CaptionTv captionTv = new CaptionTv();
        
        
        captionTv.channelUp();
        System.out.println("현재 채널: " + captionTv.channel);
        //distplayCaption()를 호출했는데 왜 출력이 안되나?
        //caption이 true일때 출력하기로 했는데 기본값이 false라서
        captionTv.displayCaption("캡션 기능 출력 메시지: hello!");
        
        captionTv.caption = true//캡션 기능을 켠다.
        captionTv.displayCaption("캡션 기능 출력 메시지: hello!");
        
    }
 
}
 
cs

 

Tv로 인스턴스를 만들었다 - tv는 Tv클래스의 멤버만 사용할 수 있다.

CaptionTv인스턴스 captionTv는 Tv클래스를 상속받았기에 자기자신의 멤버와 조상의 멤버 모두 사용할 수 있다. 

 

<출력결과>

이와같이 조상이 만들어지고 나서 자손이 만들어지는 것을 알 수 있다.

 


(예제)

<조상클래스>

Shape

멤버의 개수 2개

color과 draw메서드

1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
package sec02_exam;
//조상 클래스 (부모 클래스) 멤버개수 : 2개
public class Shape {
 
    String color = "black";
    
    public Shape() {
        System.out.println("Shape 기본 생성자 호출");
    }
    
    public void draw() {
        System.out.println("[color = " + this.color + "]");
    }
    
    
}
 
cs

 

 

<독립 클래스>

Point 

기본생성자를 호출하면 매개변수가 있는 생성자를 호출해서 x 와 y에 0 이 대입된 상태로 인스턴스가 만들어짐

1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
package sec02_exam;
//독립적인 클래스 멤버개 수: 3개(생성자와 초기화블럭은 상속 x)
public class Point {
 
    int x;
    int y;
    
    public Point() {
        this(0,0);//매개변수가 있는 또다른 생성자를 클래스내에서 호출함
        System.out.println("Point클래스의 기본 생성자 호출");
    }
    //매개변수 생성자가 존재하면 기본생성자가 자동으로 추가되지 않음
    public Point(int x, int y) {
        System.out.println("Point클래스의 매개변수가 있는 생성자 호출");
        this.x = x;
        this.y = y;
    }
    
    //x와 y의 값을 문자열로 반환
    @Override
    public String toString() {
        return "(" + this.x + ", " + this.y + ")";
    }
        
}
 
cs

 

<Shape의 자손클래스>

Circle 

멤버의 개수는 4개 (조상클래스의 멤버 포함)

기본생성자를 호출하면 Point클래스의 객체를 생성하고 반지름이 100인 객체 생성

1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
28
29
30
31
32
33
34
35
36
37
package sec02_exam;
//원이라는 도형은 원점, 반지름이 있어야 원을 그릴 수가 있다.
//Shape의 자손클래스
public class Circle extends Shape{
 
    Point center;//포함관계
    int r;
    
    public Circle() {
    //Circle(Point center, int r)을 호출하는데
    //호출하기 전에 Point클래스의 생성자 중 public Point(int x, int y)를 호출하고
    //Circle(Point center, int r)을 호출하면서 지역변수 center에게 Point를 주소를 넘겨준다
    this(new Point(0,0), 100);
    System.out.println("Circle의 기본생성자 호출");
    }
 
    public Circle(Point center, int r) {
        super();
        this.center= center;
        this.r = r;
    }
    
    //조상클래스의 멤버 메서드인 draw() 를 오버라이딩(재정의)함
    //원을 그리는 대신에 원의 정보를 출력하도록 했다.
    //오버라이딩 : 선언부가 무조건 같고, 구현부만 다르게 구현함
    
    @Override
    public void draw() {
        System.out.println("색깔 : " + this.color);
        System.out.println("원점 : ( x :" + this.center.x + ",y : " + this.center.y + ")");
        System.out.println("반지름: " + this.r);
    
    }
    
    
}
 
cs

 

<Shape의 자손클래스>

Triangle클래스

Shape를 상속받고 Point를 포함함

기본 생성자를 호출하면 Point객체 세개를 만들어서 받는 생성자 호출하고 포인트 배열에 값을 대입

1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
28
29
30
31
32
33
34
35
package sec02_exam;
//세 개의 점을 가지고 있는 삼각형(has a 관계)
public class Triangle extends Shape{
 
    Point[] p;
    
    public Triangle() {
        this(new Point(0,0),new Point(0,0),new Point(0,0));
        System.out.println("Triangle의 기본 생성자 호출");
    }
    //Point 클래스 3개(Point인스턴스 3개)를 받는 매개변수가 있는 생성자
    public Triangle(Point p1, Point p2, Point p3) {
        super();
        System.out.println("Triangle매개변수 3개짜리 생성자 호출");
        this.p = new Point[] {p1,p2,p3};
    }
    
    //Point []타입의 주소를 받는 생성자
    public Triangle(Point[] p) {
        super();
        System.out.println("매개변수 Point[]생성자 호출");
        this.p = p;
    }
    
    
    @Override
    public void draw() {
        System.out.println("[p1] : "+ this.p[0].toString());
        System.out.println("[p2] : "+ this.p[1].toString());
        System.out.println("[p3] : "+ this.p[2].toString());
        
    }
    
}
 
cs

 

<실행클래스>

1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
package sec02_exam;
 
public class DrawShapeEx {
 
    public static void main(String[] args) {
 
        Point[] p = new Point[] {new Point(10,10),new Point(20,20),new Point(30,30)};
        
        Triangle t1 = new Triangle(p);
        t1.draw();
        System.out.println("--------------------------");
        
        Circle c1 = new Circle();
        c1.draw();
        System.out.println("-----------------------------");
        
        Circle c2 = new Circle(new Point(100,100), 100);
        c2.draw();
        
    }
 
}
 
cs

p는 포인트 배열로, 포인트를 생성해서 대입하고 있다.

t1은 Triangle의 객체로 p를 받으면서 생성하고 있다.

 

c1은 기본생성자를 호출했으니 Point(0,0)과 반지름 100인 객체를 생성한다.

c2는 매개변수가있는 생성자를 호출했으니 포인트와 반지름이 코드에서 정해진 대로 인스턴스가 생성된다.

 

<출력결과>

 

포인트 배열을 만들때 Point인스턴스를 생성해서 각각 인덱스에 넘겨줬기 때문에 위에 3줄이 호출되었다.

 

Triangle 객체를 만들때 조상의 생성자 먼저 호출하므로 조상인 Shape의 기본생성자가 호출되었다.

 

 

 

728x90