[인프런 Java] 다형성 시작

코드 속의 "진돌"·2024년 3월 19일
0
post-thumbnail

✅ 다형성


다형성(Polymorphism)은 이름 그대로 “다양한 형태”, “여러 형태”를 뜻한다.
프로그래밍에서 다형성은 한 객체가 여러 타입의 객체로 취급될 수 있는 능력을 뜻한다. 보통 하나의 객체는 하나의 타입으로 고정되어 있다. 그런데 다형성을 사용하면 하나의 객체가 다른 타입으로 사용될 수 있다.


📚 다형성 핵심 이론

  • 다형적 참조
  • 메서드 오버라이딩




✅ 다형적 참조


✏️ Parent

package poly.basic;

public class Parent {

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



✏️ Child

package poly.basic;

public class Child extends Parent {

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



✏️ PolyMain

package poly.basic;

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();

    // Child child1 = new Parent();  // 자식은 부모를 담을 수 없다.

    // 자식의 기능은 호출할 수 없다. 컴파일 오류 발생
    // poly.childMethod();
  }
}



🖥️ 실행 결과



⚙️ 코드 분석

1️⃣ 부모 타입의 변수가 부모 인스턴스 참조(Parent → Parent : parent.parentMethod())

  • 부모 타입의 변수가 부모 인스턴스를 참조한다.
  • Parent parent = new Parent()
  • Parent 인스턴스를 만들었다. 이 경우 부모 타입인 Parent를 생성했기 때문에 메모리 상에 Parent만 생성된다. (자식은 생성되지 않음)
  • 생성된 참조값을 Parent 타입의 변수인 parent에 담아둔다.
  • parent.parentMethod()를 호출하면 인스턴스의 Parent 클래스에 있는 parentMethod()가 호출된다.

2️⃣ 자식 타입의 변수가 자식 인스턴스 참조(Child → Child : child.childMethod())

  • 자식 타입의 변수가 자식 인스턴스를 참조한다.
  • Child child = new Child()
  • Child 인스턴스를 만들었다. 이 경우 자식 타입인 Child를 생성했기 때문에 메모리 상에 ChildParent가 모두 생성된다.
  • 생성된 참조값을 Child 타입의 변수인 child에 담아둔다.
  • child.childMethod()를 호출하면 인스턴스의 Child 클래스에 있는 childMethod()가 호출된다.

3️⃣ 다형적 참조 : 부모 타입의 변수가 자식 인스턴스 참조 (Parent → Child : poly.parentMethod())

  • 부모 타입의 변수가 자식 인스턴스를 참조한다.
  • Parent poly = new Child()
  • Child 인스턴스를 만들었다. 이 경우 자식 타입인 Child를 생성했기 때문에 메모리 상에 ChildParent가 모두 생성된다.
  • 생성된 참조값을 Parent 타입의 변수인 poly에 담아둔다.

❗️ 부모는 자식을 담을 수 있다.

  • 부모 타입은 자식 타입을 담을 수 있다.
  • Parent poly는 부모 타입이다. new Child()를 통해 생성된 결과는 Child 타입이다. 자바에서 부모 타입은 자식 타입을 담을 수 있다.
    • Parent poly = new Child() ⇒ 성공
  • 자식 타입은 부모 타입을 담을 수 없다.
    • Child child1 = new Parent() ⇒ 컴파일 오류 발생



📚 다형적 참조

지금까지는 항상 같은 타입에 참조를 대입했다. 그래서 보통 한 가지 형태만 참조할 수 있었다.

  • Parent parent = new Parent()
  • Child child = new Child()

그런데 Parent 타입의 변수는 자신인 Parent는 물론이고, 자식 타입까지 참조할 수 있다. 만약 손자가 있다면 손자도 그 하위 타입도 참조할 수 있다.

  • Parent poly = new Parent()
  • Parent poly = new Child()
  • Parent poly = new Grandson()Child 하위에 손자가 있다면 가능

자바에서 부모 타입은 물론이고, 자신을 기준으로 모든 자식 타입을 참조할 수 있다. 이것이 바로 다양한 형태를 참조할 수 있다고 해서 다형적 참조라 한다.


✓ 다형적 참조와 인스턴스 실행

poly.parentMethod()를 호출하면 먼저 참조값을 사용해서 인스턴스를 찾는다. 그리고 다음으로 인스턴스 안에서 실행할 타입도 찾아야 한다. polyParent 타입이다. 따라서 Parent 클래스부터 시작해서 필요한 기능을 찾는다. 인스턴스의 Parent 클래스에 parentMethod()가 있다. 따라서 해당 메서드가 호출된다.


✓ 다형적 참조의 한계 (Parent → Child : poly.childMethod())

Parent poly = new Child() 이렇게 자식을 참조한 상황에서 poly가 자식 타입인 Child에 있는 childMethod()를 호출하면 어떻게 될까?

poly.childMethod()를 실행하면 먼저 참조값을 통해 인스턴스를 찾는다. 그리고 인스턴스 안에서 실행할 타입을 찾아야 한다. 호출자는 polyParent 타입이다. 따라서 Parent 클래스부터 시작해서 필요한 기능을 찾는다. 그런데 상속 관계는 부모 방향으로 찾아 올라갈 순 있지만 자식 방향으로 찾아 내려갈 수는 없다. Parent는 부모 타입이고 상위에 부모가 없다. 따라서 childMethod()를 찾을 수 없으므로 컴파일 오류가 발생한다.

이런 경우 childMethod()를 호출하고 싶으면 어떻게 해야할까? 바로 캐스팅이 필요하다.


출처 : 김영한의 실전 자바 - 기본편
https://www.inflearn.com/course/%EA%B9%80%EC%98%81%ED%95%9C%EC%9D%98-%EC%8B%A4%EC%A0%84-%EC%9E%90%EB%B0%94-%EA%B8%B0%EB%B3%B8%ED%8E%B8/dashboard

profile
매일 성장하는 주니어 개발자의 기록📝

0개의 댓글