처누

[김영한의 실전 자바 - 기본편] 다형성 본문

java

[김영한의 실전 자바 - 기본편] 다형성

처누 2024. 1. 7. 14:50

다형성이란?

 객체 지향 프로그래밍의 대표적인 특징으로는 '캡슐화', '상속', '다형성'이 있다.

 다형성은 이름 그대로 '다양한 형태', '여러 형태'를 뜻한다.

 

다형적 참조

 다형적 참조란 부모 타입의 변수가 자식 인스턴스를 참조하는 것을 의미한다. 다음 코드를 보고 이해하자.

public class Parent {

    public void parentMethod() {
        System.out.println("Parent.parentMethod");
    }
}

public class Child extends Parent{

    public void childMethod() {
        System.out.println("Child.childMethod");
    }
}

public class PolyMain {

    public static void main(String[] args) {
        System.out.println("Parent -> Parent");
        Parent parent = new Parent();
        parent.parentMethod();

        System.out.println("Child -> Child");
        Child child = new Child();
        child.parentMethod();
        child.childMethod();

        //부모 변수가 자식 인스턴스 참조(다형적 참조)
        System.out.println("Parent -> Child");
        Parent poly = new Child();
        poly.parentMethod();
    }
}

 위 코드에서 poly는 Parent타입이고, new Child()를 통해 생성된 결과는 Child타입이다. 하지만 poly.childMethod()는 호출할 수 없다. poly는 Parent타입이기 때문에 Parent클래스부터 시작해서 필요한 기능을 찾는다. 

 

 poly가 childMethod()를 호출하게 하기 위해서는 다운캐스팅을 활용하자.

 

다형성을 이루는 또 하나의 중요한 핵심 이론은 메서드 오버라이딩이다. 오버라이딩 된 메서드는 항상 우선권을 가진다.
public class Parent {

    public String value = "Parent";

    public void method() {
        System.out.println("Parent.method");
    }
}

public class Child extends Parent{

    public String value = "child";

    @Override
    public void method() {
        System.out.println("Child.method");
    }
}

public class OverridingMain {

    public static void main(String[] args) {
        //자식 변수가 자식 인스턴스 참조
        Child child = new Child();
        System.out.println("Child -> Child");
        System.out.println("value = " + child.value);
        child.method();

        //부모 변수가 부모 인스턴스 참조
        Parent parent = new Parent();
        System.out.println("Parent -> Parent");
        System.out.println("value = " + parent.value);
        parent.method();

        //부모 변수가 자식 인스턴스 참조
        Parent poly = new Child();
        System.out.println("Parent -> Child");
        System.out.println("value = " + poly.value);
        poly.method();
    }
}

poly.method()의 실행 결과는 Parent.method()가 아닌 Child.method()가 실행된다. 하위 타입인 Child.method()가 오버라이딩 되어 있기 때문에 오버라이딩 된 메서드가 우선권을 가진다. 따라서 Parent.method()가 아니라 Child.method()가 실행된다.

 

추상 클래스

 상속을 목적으로 사용되고, 부모 클래스의 역할을 담당하면서 실체인 인스턴스가 존재하지 않는, 실제 생성되면 안되는 클래스를 추상 클래스라 한다.

 추상 클래스는 'abstract' 키워드를 붙여주면 되고, 기존 클래스와 완전히 같지만 new Class()와 같이 직접 인스턴스를 생성하지 못한다.

 

추상 메서드

 부모 클래스를 상속 받는 자식 클래스가 반드시 오버라이딩 해야 하는 메서드를 부모 클래스에 정의 할 수 있다. 이것을 추상 메서드라 한다. 추상 메서드는 실체가 존재하지 않고, 메서드 바디가 없다.

 - 추상 메서드가 하나라도 있는 클래스는 추상 클래스로 선언해야 한다.

 - 추상 메서드는 상속 받는 자식 클래스가 반드시 오버라이딩 해서 사용해야 한다.

public abstract class AbstractAnimal {

    public abstract void sound();

    public void move() {
        System.out.println("동물이 움직입니다.");
    }
}

 

인터페이스

 자바는 순수 추상 클래스를 더 편리하게 사용할 수 있는 인터페이스라는 기능을 제공한다.

 인터페이스는 순수 추상 클래스와 같고, 여기에 약간의 편의 기능이 추가된다.

 - 인터페이스의 메서드는 모두 public, abstract이다.

 - 메서드에 public abstract를 생략할 수 있다.(권장)

 - 다중 구현(다중 상속)을 지원한다.

public interface InterfaceAnimal {

    void sound();
    void move();
}