[Java] 상속, 참조 자료형의 형변환, 다형성

clean·2024년 1월 2일
0

상속(Inheritance)

'extends'라는 자바 예약어로 부모 클래스를 상속 받을 수 있다. 부모 클래스를 상속 받은 자식 클래스는 부모 클래스에 선언되어 있는 public, protected 변수, 메소드를 자신의 변수, 메소드처럼 사용 가능하다.
접근 제어자가 없거나 private으로 선언된 것들은 자식 클래스에서 사용할 수 없다.

자바에서는 단일 상속만 가능하다. 즉, extends 예약어 뒤에 하나의 클래스만 쓸 수 있다.

method Overriding

자식 클래스에서 부모 클래스에 있는 메소드와 동일하게 선언하는 것을 메소드 오버라이딩이라고 한다.
접근제어자, 리턴 타입, 메소드 이름, 파라미터 타입과 개수 이 4가지가 모두 일치(=동일한 signature를 가짐)해야 메소드 오버라이딩이다.

오버라이딩을 할 때, 자식 클래스의 메소드는 부모 클래스 메소드의 접근 제어자보다 더 접근 범위를 축소해서는 안된다.
예를 들면, 부모 클래스에서 오버라이드하려는 메소드가 public으로 선언 되어있는데, 그것을 오버라이드 할때 private, protected 등으로 바꾸는 것이 불가능하다.

package javaonly;

public class Parent {
    public Parent() {
        System.out.println("Parent Constructor");
    }

    public void printName() {
        System.out.println("printName() - Parent");
    }
}
package javaonly;

public class Child extends Parent{
    public Child() {
        System.out.println("Child Constructor");
    }

    @Override
    void printName() {
        System.out.println("printName - Child");
    }
}

이런 경우에서, Child 클래스의 printName 선언 부분에서 ''printName()' in 'javaonly.Child' clashes with 'printName()' in 'javaonly.Parent'; attempting to assign weaker access privileges ('package-private'); was 'public'' 이런 에러가 발생한다.

하지만 반대로, 자식 클래스에서 부모 클래스보다 접근 범위를 확대하는 것은 허용된다.

참조 자료형의 형변환

상속을 받으면 다음과 같은 인스턴스 선언이 가능하다.

Parent p_obj = new Child();

Child 클래스에서는 Parent 클래스에 있는 메소드, 변수에 접근할 수 있다.
하지만 아래와 같은 코드를 작성하면 컴파일 에러가 발생한다.

Child child = new Parent();

자식 클래스 참조 변수에 부모 클래스 인스턴스를 담고 싶다면 명시적 형변환(casting)을 해주어야 한다.

Child child = (Child)(new Parent());

이렇게 casting을 하면 컴파일은 되지만, 런타임에 exception이 발생한다.

instanceof

'[instance 이름] instanceof [클래스이름]' 이 코드로 어떤 인스턴스가 해당 클래스에 속하는지 아닌지 여부 boolean으로 알 수 있다.

다음과 같이 코드를 짜서 실행해보면

package javaonly;

public class Inheritance {
    public static void main(String[] args) {
        Parent parent = new Parent();
        Child child = new Child();

        boolean b1 = parent instanceof Child;
        boolean b2 = child instanceof Parent;

        System.out.println("parent is Child? " + b1);
        System.out.println("child is Parent? " + b2);

    }
}
parent is Child? false
child is Parent? true

즉, 자식 클래스는 부모 클래스에 속한다. 그래서 부모 클래스 변수에 자식 클래스 인스턴스를 넣을 수 있는 것이다.
하지만 반대는 성립하지 않는다.

이러한 특징 때문에 if문과 instanceof 키워드로 인스턴스의 종류를 판단할 때는 하위에 있는 자식 클래스인지부터 검사해야한다.

다형성

Ploymorphism.

Parent p = new Parent();
Parent c = new Child();

위와 같이 형변환을 하여 인스턴스를 선언하여도, 실제 호출되는 메소드는 실제 인스턴스에서 오버라이딩한 메소드가 호출이 된다.
선언시에는 모두 같은 클래스로 선언했지만, 실제 호출되는 것은 실제 인스턴스에 따라 다르므로 이를 다형성이라고 한다.

profile
블로그 이전하려고 합니다! 👉 https://onfonf.tistory.com 🍀

0개의 댓글