7-1. 상속

Hyun Jun·2022년 1월 22일
0

자바의 정석

목록 보기
26/52
post-thumbnail
post-custom-banner

상속

상속의 정의와 장점

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

새로 작성하는 클래스의 이름 뒤에 extends 키워드와 기존 클래스 이름을 작성

class ChildClass extends ParentClass {
    ...
}

이 때 상속해주는 쪽을 조상 클래스, 상속 받는 쪽을 자손 클래스라고 부름.

자손 클래스는 조상 클래스의 멤버(변수와 메서드)를 모두 포함함.

  • 생성자와 초기화 블럭은 상속 안됨. 멤버만 상속.

  • 조상 클래스에 변경 사항이 생기면 자손 클래스에도 영향이 가지만, 반대의 경우는 해당사항이 없음

 

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

클래스 간에 포함(composite) 관계를 만들어주면 클래스를 효율적으로 재사용할 수 있음.

class Circle {
    int x; // 원점의 x 좌표
    int y; // 원점의 y 좌표
    int r; // 반지름
}

class Point {
    int x; // x 좌표
    int y; // y 좌표
}

Circle 클래스의 멤버 변수인 원점의 좌표들은 Point 클래스를 활용하여 나타낼 수 있음

class Circle {
    Point c = new Point();
    int r =;
}

이렇게 다른 클래스를 멤버 변수로 활용하는 포함 관계를 통해 좀 더 구조적인 코드를 짤 수 있음.

 

클래스 간의 관계 결정하기

상속 관계, 포함 관계를 각각 어떻게 구분하여 적용해주면 좋은가?

  • 상속 관계: A는 B이다(또는 B의 일종이다)

  • 포함 관계: A는 B를 가지고 있다

 

예시)

  • Rectangle은 Point이다 (X)

  • Rectangle은 Point를 가지고 있다 (O)

    → 포함 관계로 설정

    class Rectangle {
        Point[] p = new Point[4];
        ...
    }
  • Rectangle은 Polygon이다. (O)

    → 상속 관계로 설정

    class Rectangle extends Polygon {
        ...
    }

 

예시2)

Deck은 Card를 가지고 있다 (포함 관계 성립)

class DeckTest {
        public static void main(String[] args) {
            Deck d = new Deck();
            Card c = d.pick(0); // 덱의 맨 앞 카드 뽑기
            System.out.println(c); // 참조변수를 출력하면, Card 클래스에서 오버라이드(override)했던 toString 메서드가 호출됨

            d.shuffle();
            c = d.pick(0); // 섞인 덱에서 맨 앞 카드 뽑기
            System.out.println(c);
        }
}

class Deck {
        final int TOTAL_COUNT = 52;
        Card[] cardArr = new Card[TOTAL_COUNT];
        Deck() {
            int i = 0;
            for (int kind = Card.KIND_MAX; kind > 0; kind--) {
                for (int num = 0; num < Card.NUM_MAX; num++) {
                    cardArr[i++] = new Card(kind, num + 1);
                }
            }
        }
        Card pick(int index) {
            return cardArr[index];
        }
        Card pick() {
            int randomIndex = (int)(Math.random() * TOTAL_COUNT);
            return cardArr[randomIndex];
        }
        void shuffle() {
            for (int i = 0; i < cardArr.length; i++) {
                int randomIndex = (int)(Math.random() * TOTAL_COUNT);
                Card tmp = cardArr[i];
                cardArr[i] = cardArr[randomIndex];
                cardArr[randomIndex] = tmp;
            }
        }
}

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 num;

        Card() {
            this(SPADE, 1);
        }
        Card(int kind, int num) {
            this.kind = kind;
            this.num = num;
        }
        public String toString() {
            String[] kinds = {"", "CLOVER", "HEART", "DIAMOND", "SPADE"};
            String nums = "0A23456789XJQK";
            return String.format("kind: %s num: %c", kinds[this.kind], nums.charAt(this.num));
        }
        // 조상 클래스인 Object의 메서드 중 toString을 오버라이드(override)한 것.
}

클래스 안에 toString 메서드를 오버라이드 해놓으면, 인스턴스를 출력하거나 참조변수를 문자열과 연산할 때 자동적으로 문자열로 변환시켜줌.

 

단일 상속

쉽게 말해 동시에 여러 부모로부터 상속 받을 수 없다는 뜻.

다중 상속을 허용하는 C++과는 다르게 Java에서는 클래스간의 명확한 관계 형성을 위해 단일 상속만을 허용함.

다중 상속의 문제점: 서로 다른 부모클래스로부터 이름이 겹치는 멤버들을 받아오면 구별할 수 없음.

 

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

모든 클래스는 Object 클래스의 상속을 받음.

따라서 Java의 모든 클래스에서는 Object 클래스의 멤버들을 사용할 수 있음. (이후에 다뤄질 예정)

profile
Back-end Engineer 👨‍💻
post-custom-banner

0개의 댓글