반응형

           

  JAVA Study





1. 상속 (inheritance)


- 기존 클래스를 재사용하여 새로운 클래스를 작성하는 것 


- 보다 적은 양의 코드로 새로운 클래스 작성 가능 & 코드를 공통적으로 관리할 수 있기 때문에 코드의 추가 및 변경이 매우 용이


- 새로 작성하고자 하는 클래스 이름 뒤에 상속받고자 하는 클래스의 이름을 키워드 'extends'와 함께 써줌


class child extends parent{

// parent 클래스를 상속받은 child 클래스

}


- 상속해주는 클래스를 조상클래스, 상속 받는 클래스를 자손클래스라고 함

: 조상클래스 - 부모 클래스, 상위클래스, 기반 클래스

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


- 자손 클래스는 조상 클래스의 모든 멤버를 상속 받음

: child 클래스는 parent 클래스의 모든 멤버들을 포함

: child 클래스에 새로운 코드가 추가되어도 조상인 parent클래스는 아무 영향을 받지 않음

: 자손클래스는 조상 클래스의 모든 멤버를 상속받으므로 항상 조상 클래스보다 같거나 많은 멤버를 갖음


- 생성자와 초기화 블럭은 상속되지 않음, 멤버만 상속


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


class parent { }

class child extends parent { }

class child2 extends parent { }


: child와 child2클래스 모두 parent클래스를 상속받음

: 클래스 간 관계에서 형제관계는 없음

: child와 child2 클래스에 공통적으로 추가되어야 하는 멤버변수나 메서드가 있다면 공통조상인 parent에 작성


class parent { }

class child extends parent { }

class grandchild extends child{ }


: 자손 클래스는 조상 클래스의 모든 멤버를 물려받으므로 grandchild클래스는 child 클래스의 모든 멤버, child클래스의 조상인 parent 클래스로부터 상속받은 멤버까지 상속받게 됨

: grandchild 클래스는 child의 자손이면서 parent의 자손이기도 함

: child클래스는 grandchild클래스의 직접조상, parent 클래스는 grandchild 클래스의 간접 조상이 됨

: parent클래스에 변수를 추가하면 parent를 상속받고 있는 child, grandchild클래스에 변수가 공통적으로 추가됨


- 자손 클래스의 인스턴스를 생성하면 조상 클래스의 멤버도 함께 생성되므로 따로 조상클래스의 인스턴스를 생성하지 않아도 조상클래스의 멤버들을 사용할 수 있음


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
38
39
40
41
42
class Tv{
    boolean power; //전원상태 on/off
    int channel; //채널
    
    void power(){
        power = !power;
    }
    
    void channelUp(){
        ++channel;
    }
    
    void channelDown(){
        --channel;
    }
    
}
 
class CaptionTv extends Tv{
    boolean caption; //캡션상태 on/off
    void displayCaption (String text){
        if(caption){ //캡션 상태가 on(true)일 때만 text를 보여준다.
            System.out.println(text);
        }
    }
}
 
public class CaptionTvTest{
 
    public static void main(String[] args) {
    
        CaptionTv t = new CaptionTv(); //자손 클래스의 인스턴스를 생성하면 조상클래스의 변수와 메서드를 사용할 수 있다.
        
        t.channel = 10;   // 조상 클래스에서 상속받은 멤버
        t.channelUp();      // 조상 클래스에서 상속받은 멤버 
        System.out.println(t.channel); // channel은 11
        
        t.displayCaption("Hello world1"); // 캡션 상태가 on이 아니므로 출력되지 않음
        t.caption = true;
        t.displayCaption("Hello world2"); // Hello world2 출력
    }
}
cs


- 클래스간의 관계 (포함관계)

클래스 간에 포함관계를 맺어 상속외에 클래스를 재사용하는 방법

: 한 클래스의 멤버변수로 다른 클래스 타입의 참조변수를 선언하는 것을 뜻함


1
2
3
4
5
6
7
8
9
10
class Circle{
    int x;    // 원점의 x좌표
    int y;    // 원점의 y좌표
    int r;    // 반지름
}
 
class Point{
    int x;    // x좌표
    int y;    // y좌표
}
cs


: Point 클래스를 재사용해서 Circle 클래스를 작성


1
2
3
4
5
6
7
8
9
class Circle{
    Point c = new Point(); //원점
    int r;    // 반지름
}
 
class Point{
    int x;    // x좌표
    int y;    // y좌표
}
cs
   

- 클래스간의 관계 결정하기

: 상속관계를 맺을 지, 포함관계를 맺을지 결정

- ~은 ~이다. : 상속관계

- ~은 ~을 가지고 있다. : 포함관계

ex. 원은 점이다 / 원은 점을 가지고 있다. => 원은 점을 가지고 있다가 더 자연스러우므로 포함관계를 맺는 것이 옳다


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
38
39
40
41
42
43
44
45
46
47
48
49
50
51
52
53
54
55
56
57
58
59
60
61
62
63
64
65
66
67
68
69
70
71
72
73
class DrawShap{
    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 Shap{
    String color="black";
    void draw(){
        System.out.print("color = "+color);
    }
}
 
class Point{
    int x;
    int y;
    
    Point(int x, int y){
        this.x = x;
        this.y = y;
    }
    Point(){
        this(0,0);
    }
    String getXY(){
        return "("+x+","+y+")"//x와 y의 값을 문자열로 반환
    }
}
 
class Circle extends Shape{
    Point center;
    int r;
    
    Circle(){
        this(new Point(0,0),100); // Circle(Point center,int r)를 호출
    }
    
    Circle(Point Center, int r){
        this.center =center;
        this.r = r;
    }
    
    void draw(){ //원을 그리는 대신에 원의 정보를 출력하도록 했다.
        System.out.print("");
    }
}
 
class Triangle extends Shape {
    Point[] p = new Point[3];
    
    Triangle(Point[] p){
        this.p = p;
    }
    
    void draw(){
         System.out.print("[p1]=("+p[0].getXY()+"), [p2]=("+p[1].getXY()+"), [p3]=("+p[2].getXY()+")");
    }
    
}
 
 
 
 
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
25
26
27
28
29
30
31
32
33
34
35
36
37
38
39
40
41
42
43
44
45
46
47
48
49
50
51
52
53
54
55
56
57
58
59
60
61
62
63
64
65
66
67
68
69
70
71
72
73
74
75
76
77
78
package apple2;
 
public class DectTest {
 
    public static void main(String[] args) {
        Deck d = new Deck(); // 카드 한 벌 만듦
        Card c = d.pick(0);  // 섞기 전 제일 위의 카드를 뽑는다.
        System.out.println(c); //뽑은 카드 확인
        
        d.shuffle(); // 카드를 섞음
        c = d.pick(0); // 섞은 후 제일 위의 카드를 뽑는다.
        System.out.println(c); //뽑은 카드 확인
    }
}
 
class Deck{
    final int CARD_NUM =52// 카드의 개수
    Card cardArr[] = new Card[CARD_NUM]; // Card 객체 배열 포함
    
    Deck(){ // Deck의 카드를 초기화
        int i=0;
        
        for(int k=Card.KIND_MAX; k>0; k--){
            for(int n=0; n<Card.NUM_MAX; n++){
                cardArr[i++= new Card(k, n+1);
            }
        }
    }
    
    Card pick(int index){    // 지정된 위치에 있는 카드 하나를 꺼내서 반환
        return cardArr[index];
    }
    
    Card pick(){ // Deck에서 카드하나 선택
        int index = (int)(Math.random() * CARD_NUM);
        return pick(index);
    }
    
    void shuffle(){ // 카드의 순서를 섞는다
        for(int i=0; i<cardArr.length; i++){
            int r = (int)(Math.random() * CARD_NUM);
            
            Card temp = cardArr[i];
            cardArr[i] = cardArr[r];
            cardArr[r] = temp;
        }
    }
    
}
 
class Card{
    static final int KIND_MAX = 4// 카드 무늬의 수
    static final int NUM_MAX = 13// 무늬별 카드 수
    
    static final int SPADE = 4;
    static final int DIAMOND = 3;
    static final int HEART = 2;
    static final int CLOVER = 1;
    
    int kind;
    int number;
    
    Card() {
        this(SPADE,1);
    }
    
    Card(int kind, int number){
        this.kind = kind;
        this.number = number;
    }
    
    public String toString(){
        String[] kinds = {"","CLOVER","HEART","DIAMOND","SPADE"};
        String numbers = "0123456789XJQK"//숫자10은 X로 표현
        
        return "kind : "+kinds[this.kind] + ", number : "+numbers.charAt(this.number);
    }
}
cs



- 단일 상속 (Single inheritance)

: 자바는 단일상속만을 허용한다 -> 하나 이상의 클래스로부터 상속받을 수 없음


- Object 클래스 - 모든 클래스의 조상

: Object 클래스는 모든 클래스 상속계층도의 최상위에 있는 조상클래스

: 다른 크랠스로부터 상속 받지 않는 모든 클래스들은 자동적으로 Object클래스로부터 상속받게 함

: 모든 클래스의 조상이 되는 클래스

: 만일 다른 클래스를 상속받더라도 상속계층도를 따라 조상클래스를 올라가다보면 마지막 최상위 조상은 Object클래스임



2. 오버라이딩 (overriding)


- 조상 클래스로부터 상속받은 메서드의 내용을 변경하는 것


1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
class Point {
    int x;
    int y;
 
    String getLocation() {
        return "x : "++ "y : "+y;
    }
}
 
class Point3D extends Point {
    int z;
    
    String getLocation() {
        return "x : "+x+", y : "+y+", z : "+z;
    }
}
cs

 

: Point 클래스의 getLocation() 은 한 점의 x,y좌표를 문자열로 반환하도록 작성되었다.

: 이 두 클래스는 서로 상속관계에 있으므로 Point3D클래스는 Point 클래스로부터 getLocation()을 상속받은 후 자신에 맞게 z축의 좌표를 포함하여 반환하도록 오버라이딩 하였다


- 오버라이딩 조건

: 자손클래스에서 오버라이딩하는 메서드는 조상 클래스의 메서드와 이름 / 매개변수 / 반환타입이 같아야 한다

: 선언부가 서로 일치해야 함

: 접근 제어자와 예외는 제한된 조건 하에서만 다르게 변경할 수 있음

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

- 조상 클래스의 메서드보다 많은 수의 예외를 선언할 수 없음

- 인스턴스메서드를 static메서드로 또는 그 반대로 변경할 수 없음


- 오버로딩 vs 오버라이딩

: 오버로딩 (overloading) - 기존에 없는 새로운 메서드를 정의하는 것(new)

: 오버라이딩(overriding) - 상속받는 메서드의 내용을 변경하는 것(change, modify)


1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
class Point {
    int x;
    int y;
 
    String getLocation() {
        return "x : "++ "y : "+y;
    }
}
 
class Point3D extends Point {
    int z;
    
    String getLocation() { //
        return "x : "+x+", y : "+y+", z : "+z;
    }
    String getLocation(int i){ //오버로딩
    }
}
cs



- super

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

: 멤버변수와 지역변수의 이름이 같을 때 this를 붙여서 구별했듯이 상속받은 멤버와 자신의 클래스에 정의된 멤버의 이름이 같을 때 super를 붙여서 구별할 수 있음

: 조상 클래스로 상속받은 멤버도 자손 클래스의 멤버이므로 super대신 this를 사용할 수 있음

: 조상 클래스의 멤버와 자손클래스의 멤버가 중복 정의되어 서로 구별해야하는 경우에만 super를 사용하는 것이 좋음

: 모든 인스턴스변수에는 자신이 속한 인스턴스 주소가 지역변수로 저장되는데, 이것이 참조변수인 this와 super의 값이 됨

: static메서드는 인스턴스와 관련없기때문에 super를 사용할 수 없음  (인스턴스에서만 사용할 수 있음)


1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
class Point {
    int x;
    int y;
 
    String getLocation() {
        return "x : "++ "y : "+y;
    }
}
 
class Point3D extends Point {
    int z;
    
    String getLocation() { //오버라이딩
        return "x : "+x+", y : "+y+", z : "+z;
        return super.getLocation() + ", z : "+z; //조상 메서드 호출
    }
 
}
cs


: 조상클래스의 메서드의 내용에 추가적으로 작업을 덧붙이는 경우 super를 사용해 조상클래스의 메서드를 포함시키는 것이 좋음 

- 후에 조상 클래스의 메서드가 변경되더라도 변경된 내용이 자손클래스의 메서드에 자동적으로 반영될 것이기 때문


- super()

: 조상 클래스의 생성자를 호출하는데 사용됨

: 자손 클래스의 인스턴스를 생성하면, 자손과 조상의 멤버가 모두 합쳐진 하나의 인스턴스가 생성되는데, 이 때 조상 클래스 멤버의 초기화 작업이 수행되어야 함 -> 자손클래스의 생성자에서 조상 클래스의 생성자를 호출

: Object클래스를 제외한 모든 클래스의 생성자의 첫 줄에서 조상클래스의 생성자를 호출, 그렇지 않으면 컴파일러가 생성자의 첫 줄에 '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
29
30
31
32
33
34
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(x,y);    // 조상클래스 생성자 
       // this.x = x;
       // this.y = y;
        this.z = z;
    }
 
    String getLocation() {
        return "x : "+x+", y : "+y+", z : "+z;
    }
}
 
cs






반응형

'프로그래밍 > JAVA' 카테고리의 다른 글

[JAVA] 7 객체지향 프로그래밍 2-3  (0) 2017.07.22
[JAVA] 7 객체지향 프로그래밍 2-2  (0) 2017.07.21
[JAVA] 6 객체지향 프로그래밍1  (0) 2017.07.05
[JAVA] 배열 예제  (0) 2017.07.04
[JAVA] 5 배열 (Array)  (0) 2017.07.03

+ Recent posts