ABOUT ME

-

Today
-
Yesterday
-
Total
-
  • 다형성(Polymorphism) - 부모와 그 자식에 관하여(상속)
    Language/Java 2020. 4. 4. 12:15

     

     

    public class Main {
        public static void main(String[] args){
            Person a = new Student("catnap", 24);
            a.print();
        }
    }

     

    위 예시의 세 번째 라인의 코드와 같은 형식을 봐온 적이 있는가?

    그렇다면 저 코드가 무엇을 의미하고 있는 지와 왜 저렇게 사용하는 지를 아는가?

    이 글은 저 코드가 어떠한 의미를 가지고 있는지, 다형성과 어떻게 연관되어 있는 지를 설명한다.

     

    ※ 본문은 다형성의 개념을 어느정도 이해하지만(오버로딩과 오버라이딩), 상속에 있어서 다형성의 개념이 어떻게 적용되는 지 이해가 잘 안가시는 분들을 위한 글입니다. 충분히 다형성을 이해하고 계신다면, 뒤로가기를 눌러주세요. 

     


    먼저 위 예시의 세 번째 라인을 설명하고 넘어가도록 하겠다. 

    저 코드의 의미는 "Student 생성자를 호출하여, Student 인스턴스를 만들고, 이를 Person 클래스의 인스턴스로 변환하라."이다.

     

    저 코드가 어떻게 다형성과 관련이 있는지 살펴보자.

     

    먼저 예시의 Person과 같은 부모 클래스의 인스턴스를 생성하는 방법에는 무엇이 있을까? 이 부분은 충분히 고민해보길 바란다.

    더보기

    정답은 생성자를 호출하는 것인데, 두 가지 방법이 존재한다.

    1. 본인의 생성자를 호출한다.

    2. 자식의 생성자를 호출하여, 부모 타입으로 변환시킨다.

    두 번째 방법과 같이 자식의 생성자를 호출하여, 부모 타입으로 변환시키는 게, 마치 생성자 오버로딩의 개념과 유사하다. 

     

    Person a = new Person("name");
    Person b = new Person("Jo", 24);
    
    Person c = new Student("Haen", 24);​

     

    위 코드의 2번째와 마지막 코드를 보면 유사하다고 느낄 수 있다.

     

    이렇게 다형성은 자식 클래스 타입을 부모 클래스 타입으로 선언할 수 있게 만든다.

     

    이제 흔히 생겨나는 두 가지 질문을 해결해 보도록 하자.

     

    1. 그렇다면 왜 저런 방식으로 코드를 사용하나요?

    부모 클래스의 생성자를 다양하게 만드는 것은 불편한 일이다.

    File I/O의 InputStream을 통해 설명하자면, InputStream은 다양한 형태의 데이터 입력을 받을 수 있다. 

    사용자의 입력, 파일 데이터 등 다양한 형태의 입력이 존재할 수 있는데, 이에 해당하는 각각의 생성자를 만드는 것은 상상만 해도 힘들거나 혹은 불가능한 일처럼 느껴진다.

    뿐만 아니라, 해당 데이터를 읽는 메서드가 존재한다면, 각각의 형태에 맞는 메서드를 전부 오버로딩 해줘야 한다.

     

    이 때문에 자식 클래스를 만들어 부모클래스 타입으로 변환을 시켜주는 것이다. 

    자식 클래스 생성자를 호출하여 인스턴스를 만들게 되면, 각각의 의미에 맞게 생성자를 호출할 수 있고, 뿐만 아니라 해당 자식 클래스의 메서드 오버라이딩을 통해 데이터를 읽어낼 수도 있다.

     

    public class Main {
        public static void main(String[] args){
            Person a = new Student("haenuu", 24);
            a.print(); // Student 메서드 호출: haenuu, 나이: 24
            Person b = new Teacher("Haen", "Computer");
            b.print(); // Techaer 메서드 호출: Haen, 과목: Computer
        }
    }

     

    위 코드가 본문의 글의 의미를 더욱 잘 이해시켜줄 것이다.

     

    2. 그렇다면 자식 클래스 생성자를 만들어 사용하는 이유는 알겠는데, 왜 부모 클래스 타입으로 변환시키나요?

    그냥 자식 클래스 타입으로 냅두는 게 낫지 않나요?

    중요한 건 "왜 저렇게 사용하냐에 대한 대답보다, 저렇게도 사용이 가능하다."일 것이다.
    List<Person> list = new ArrayList<>(); 같은 코드를 사용하려 한다면 어떨까요?

    저러한 방식이 사용이 불가능하면, list에 a, b를 추가하는 것은 불가능한 일이 될 것이다. 하지만 부모 참조변수가 모든 자식 객체에 대해 접근이 가능하도록 함으로써, 위 list에 Person의 자식 객체라면 어떠한 타입의 객체여도 추가가 가능하게 만들 수 있다.

     

    생각보다 처음 시작말에 비해 미흡한 대답이 된 거 같다.. 아래 사이트를 참고하면 더욱 이해가 잘 될 것이다.

    http://www.corejavaguru.com/blog/java/new-child

     

    Java | Parent p = new Child() | CoreJavaGuru

    In Java, it is called as up-casting. It is nothing but polymorphism. If we don't know exact runtime type of object then we should use this approach(polymorhism). The advantage is Parent reference can hold any child class object.

    www.corejavaguru.com

     

     

     

    'Language > Java' 카테고리의 다른 글

    Sort a Map<Key, Value> by values  (0) 2020.04.03

    댓글

Designed by Tistory.