자바 상속, 다형성

U_U0_0·2022년 5월 4일
0
post-thumbnail

TCP SCHOOL - 자바 정리 #5

상속

상속은 캡슐화, 추상화와 더불어 객체 지향 프로그래밍을 구성하는 중요한 특징 중 하나이다.

class 자식클래스이름 extend 부모클래스이름 { ... }

자식 클래스에는 부모 클래스의 필드와 메소드만 상속되며, 생성자와 초기화 블록은 상속되지 않는다.
부모 클래스의 접근 제어가 private이나 default로 설정된 멤버는 자식 클래스에서 상속받지만 접근할 수는 없다.

Object 클래스

자바에서 Object 클래스는 모든 클래스의 부모 클래스가 되는 클래스.
자바의 모든 클래스는 자동으로 Object 클래스의 모든 필드와 메소드를 상속받기 때문에, 상속을 명시하지 않아도 Object 클래스의 모든 멤버를 자유롭게 사용할 수 있다.

super, super()

super 키워드

부모 클래스로부터 상속받은 필드나 메소드를 자식 클래스에서 참조하는 데 사용하는 참조 변수.
부모 클래스의 멤버와 자식 클래스의 멤버 이름이 같을 경우 super 키워드를 사용하여 구별할 수 있다.
super 참조 변수를 사용하여 부모 클래스의 멤버에 접근한다.
this와 마찬가지로 super 참조 변수를 사용할 수 있는 대상도 인스턴스 메소드뿐이며, 클래스 메소드에서는 사용할 수 없다.

class Parent {
    int a = 10;
}

class Child extends Parent {
    int a = 20;

    void display() {
        System.out.println(a);
        System.out.println(this.a);
        System.out.println(super.a);
    }
}

public class Inheritance03 {
    public static void main(String[] args) {
        Child ch = new Child();
        ch.display();
    }
}

// 20
// 20
// 10

super() 메소드

this() 메소드가 같은 클래스의 다른 생성자를 호출할 때 사용된다면, super() 메소드는 부모 클래스의 생성자를 호출할 때 사용된다.
부모 클래스의 멤버를 초기화하기 위해서는 자식 클래스의 생성자에서 부모 클래스의 생성자까지 호출해야 한다.

자바 컴파일러는 부모 클래스의 생성자를 명시적으로 호출하지 않는 모든 자식 클래스의 생성자 첫 줄에 자동으로 super() 명령문을 추가한다.

class Parent {
    int a;
    Parent() { a = 10; }
    Parent(int n) { a = n; }
}

class Child extends Parent {
    int b;

    Child() {//super(40);
        b = 20;
    }
    
    void display() {
        System.out.println(a);
        System.out.println(b);
    }
}

public class Inheritance04 {
    public static void main(String[] args) {
        Child ch = new Child();
        ch.display();
    }
}

// 10 (1번 해제 시 40)
// 20

메소드 오버라이딩

메소드 오버로딩(overloading)은 서로 다른 시그니처를 갖는 여러 메소드를 하나의 이름으로 정의하는 것이고, 메소드 오버라이딩(overriding)은 상속 관계에 있는 부모 클래스에서 이미 정의된 메소드를 자식 클래스에서 같은 시그니쳐를 갖는 메소드로 다시 정의하는 것이다.

메소드 오버라이딩의 조건은 다음과 같다.

  1. 메소드의 선언부는 기존 메소드와 완전히 같아야 한다. 하지만 메소드의 반환 타입은 부모 클래스의 반환 타입으로 타입 변환할 수 있는 타입이라면 변경 가능하다.
  2. 부모 클래스의 메소드보다 접근 제어자를 더 좁은 범위로 변경할 순 없다.
  3. 부모 클래스의 메소드보다 더 큰 범위의 예외를 선언할 수 없다.
class Parent {
    void display() { System.out.println("부모 클래스의 display() 메소드입니다."); }
}

class Child extends Parent {
    // 오버라이딩된 display() 메소드
    void display() { System.out.println("자식 클래스의 display() 메소드입니다."); }
    void display(String str) { System.out.println(str); } // 오버로딩된 display() 메소드
}

public class Inheritance06 {
    public static void main(String[] args) {
        Child ch = new Child();
        ch.display();
        ch.display("오버로딩된 display() 메소드입니다.");
    }
}

// 자식 클래스의 display() 메소드입니다.
// 오버로딩된 display() 메소드입니다.

간단히 정의하면 오버로딩(overloading)은 새로운 메소드를 정의하는 것이고, 오버라이딩(overriding)은 상속받은 기존의 메소드를 재정의하는 것이다.

다형성

다형성(polymorphism)이란 하나의 객체가 여러 가지 타입을 가질 수 있는 것을 의미한다. 부모 클래스 타입의 참조 변수로 자식 클래스 타입의 인스턴스를 참조할 수 있다.

class Parent { ... }
class Child extends Parent { ... }

...

Parent pa = new Parent(); // 허용
Child ch = new Child();   // 허용
Parent pc = new Child();  // 허용
Child cp = new Parent();  // 오류 발생.

클래스는 상속을 통해 확장될 수는 있어도 축소될 수는 없으므로, 자식 클래스에서 사용할 수 있는 멤버의 개수가 언제나 부모 클래스와 같거나 많게 된다. 참조 변수가 사용할 수 있는 멤버의 개수가 실제 인스턴스의 멤버 개수보다 같거나 적어야 참조할 수 있기 때문에 자식 클래스 타입의 참조 변수로는 부모 클래스 타입의 인스턴스를 참조할 수 없다.

참조 변수의 타입 변환

  1. 서로 상속 관계에 있는 클래스 사이에만 타입 변환을 할 수 있다.
  2. 자식 클래스 타입에서 부모 클래스 타입으로의 타입 변환은 생략할 수 있다.
  3. 부모 클래스 타입에서 자식 클래스 타입으로의 타입 변환은 반드시 명시해야 한다.
// (변환할타입의클래스이름) 변환할참조변수

class Parent { ... }
class Child extends Parent { ... }
class Brother extends Parent { ... }

...

Parent pa01 = null;
Child ch = new Child();
Parent pa02 = new Parent();
Brother br = null;

pa01 = ch;          // pa01 = (Parent)ch; 와 같으며, 타입 변환을 생략할 수 있음.
br = (Brother)pa02; // 타입 변환을 생략할 수 없음.
br = (Brother)ch;   // 직접적인 상속 관계가 아니므로, 오류 발생.
profile
u0u0u0

0개의 댓글

관련 채용 정보