[윤성우의 열혈 Java 프로그래밍] Chapter 14 - 클래스의 상속 1: 상속의 기본

Update:     Updated:

카테고리:

태그:

14-1. 상속의 기본 문법 이해

- 상속에 대한 매우 치명적인 오해

상속의 이유와 목적에 대해 설명할 때, 단순히 이렇게 답하는 경우가 있다.

상속은 코드의 재활용을 위한 문법이다..?

하지만 객체지향 기반의 개발을 공부하다보면 상속을 단순히 코드의 재활용을 위한 문법이라기보단 다음과 같은 설명이 더 적합하다.

연관된 일련의 클래스들에 대해 공통적인 규약(규칙)을 정의할 수 있다.

- 상속의 가장 기본적인 특성

상속을 단순하게 설명하면,

기존에 정의된 클래스에 메소드와 변수를 추가하여 새로운 클래스를 정의하는 것이다.

Man 클래스를 상속하여 새로운 클래스 BusinessMan 클래스를 만들어보자.

class Man {
    String name;
    
    public void tellYourName(){
        System.out.println("My name is " + name);
    }
}
class BusinessMan extends Man { // Man을 상속하는 BusinessMan
    String company;
    String position;

    public void tellYourInfo(){
        System.out.println("My company is " + company);
        System.out.println("My position is " + position);
        tellYourName(); // Man 클래스를 상속했기 때문에 호출 가능!
    }
}

image image

- 상속과 생성자

class SuperCLS {
    public SuperCLS() {
        System.out.println("Super Class!!");
    }
}

class SubCLS extends SuperCLS{
    public SubCLS() {
        System.out.println("Sub Class!!");
    }
}

public class SuperSubCon {
    public static void main(String[] args) {
        new SubCLS();
    }
}

image

  1. 하위 클래스의 인스턴스 생성 시 상위 클래스, 하위 클래스의 생성자 ‘모두’ 호출된다.
  2. 하위 클래스의 인스턴스 생성 시 상위 클래스의 생성자가 ‘먼저’ 호출된다.


그렇다면, 상위 클래스의 생성자가 여러 개 있을 시 어떻게 명시적으로 호출할 수 있을까?

class SuperCLS {
    public SuperCLS() { // 1
        System.out.println("Con: SuperCLS()");
    }
    public SuperCLS(int i) {    // 2
        System.out.println("Con: SuperCLS(int i)");
    }
    public SuperCLS(int i, int j) { // 3
        System.out.println("Con: SuperCLS(int i, int j)");
    }
}

class SubCLS extends SuperCLS { // super(); // 상위 클래스의 생성자를 명시적으로 호출하지 않으면 자동으로 호출됨
    // super를 이용한 상위 클래스의 생성자 호출문은 생성자의 첫 문장에 들어가야 함
    public SubCLS() {
        System.out.println("Con: SubCLS()");
    }
    public SubCLS(int i) {
        super(i);   // 상위 클래스의 2번 메소드 호출
        System.out.println("Con: SubCLS(int i)");
    }
    public SubCLS(int i, int j) {
        super(i, j);    // 상위 클래스의 3번 메소드 호출
        System.out.println("Con: SubCLS(int i, int j)");
    }
}

public class SuperSubCon2 {
    public static void main(String[] args) {
        System.out.println("1. ");
        new SubCLS();
        System.out.println();

        System.out.println("2. ");
        new SubCLS(1);
        System.out.println();

        System.out.println("3. ");
        new SubCLS(1, 2);
        System.out.println();
    }
}

image

- 상속 관계에 있는 두 클래스의 적절한 생성자 정의

모든 멤버는 자신이 속한 클래스에서 초기화되는 것이 좋다.

따라서, 상속에서도 마찬가지로 상위 클래스의 멤버는 상위 클래스의 생성자를 통해서 초기화해야한다.
앞서 만든 BusinessMan 클래스를 리펙토링해보자!

class Man {
    String name;

    public Man(String name){
        this.name = name;
    }

    public void tellYourName() {
        System.out.println("My name is " + name);
    }
}

class BusinessMan extends Man{
    String company;
    String position;

    public BusinessMan(String name, String company, String position) {
        super(name);
        this.company = company;
        this.position = position;
    }

    public void tellYourInfo() {
        System.out.println("My company is " + company);
        System.out.println("My position is " + position);
        tellYourName();
    }
}

public class MyBusinessMan {
    public static void main(String[] args) {
        BusinessMan man = new BusinessMan("Hi-June", "TUK", "Developer");
        man.tellYourInfo();
    }
}

image

- 단일 상속만을 지원하는 자바

자바는 프로그램이 과도하게 복잡해지는 것을 방지하기 위해 단일 상속만을 지원한다.
하나의 클래스가 상속할 수 있는 클래스의 수가 최대 하나라는 것을 의미한다.

(참고) 다중 상속을 하게 되면 어떤 문제가 생길까?

  1. 애매한 상황이 발생한다.
    image
    동일한 이름을 가진 print()를 상속받을 때 문제가 생긴다.

  2. 다이아몬드 문제
    image
    show() 메소드의 경로에 대해서 애매한 문제가 발생한다.

14-2. 클래스 변수, 클래스 메소드와 상속

- static 선언이 붙는 '클래스 변수'와 '클래스 메소드'의 상속

클래스 변수와 클래스 메소드의 특징은 다음과 같다.

  1. 인스턴스의 생성과 상관 없이 접근이 가능하다.
  2. 클래스 내부와 외부에서(접근 수준 지시자가 허용하면) 접근이 가능하다.
  3. 클래스 변수와 클래스 메소드가 위치한 클래스 내에서는 직접 접근이 가능하다.
class SuperCLS {
    static int count = 0;   // 클래스 변수

    public SuperCLS() {
        count++;    // 클래스 내에서는 직접 접근이 가능
    }
}

클래스 변수는 인스턴스의 멤버로써 존재하지 않는다.
따라서, 이를 상속하는 하위 클래스의 멤버로도 존재할 수 없다.
일반적으로 static 변수에 접근하듯이 접근하면 된다.

Java lang 카테고리 내 다른 글 보러가기

댓글 남기기