다형성과 다형성을 사용하는 이유

이승준·2021년 7월 25일
1

Java Study

목록 보기
8/12

다형성(polymorphism)이란?


  1. 여러가지 형태를 가질 수 있는 것.
  2. 하나의 메서드나 클래스가 있을 때 이것들이 다양한 방법으로 동작하는 것. 대표적으로 오버로딩, 오버라이딩이 있다.
  3. 하나의 참조변수로 여러 타입의 객체를 참조할 수 있음. 즉, 조상타입의 참조변수로 자손타입(상속관계)의 객체를 참조하여 다룰 수 있는 것이 다형성의 기본 개념.

Animal.java

public class Animal { 
    public void move() { 
        System.out.println("동물이 움직임."); 
    } 
    public  void eating() { 
        System.out.println("동물이 음식을 먹음."); 
    } 
}

Human.java

public class Human extends Animal { 
    @Override 
    public void move() { 
        System.out.println("사람이 두 발로 움직임."); 
    } 
    public void readBook() { 
        System.out.println("사람이 책을 읽음."); 
    } 
}

Tiger.java

public class Tiger extends Animal { 
    @Override 
    public void move() { 
        System.out.println("호랑이가 움직임."); 
    } 
    public void hunt() { 
        System.out.println("호랑이가 사냥을 함."); 
    } 
}

main.java

public class Main { 
    public static void main(String[] args) {
        Animal human = new Human();
        Animal tiger = new Tiger();
        human.move();  //사람이 두발로 움직임.
        tiger.move();  //호랑이가 움직임.
    }
}
  • Animal 이라는 참조 변수로, Human 과 Tiger 객체를 참조 할 수 있다.
  • move 메서드를 override 함으로써 각 Human과 Tiger 객체에서 재정의.
  • Animal이라는 객체를 수정하지 않고,  move 기능 재정의.
  • But, human이나 tiger 변수는 참조타입이 Animal이기 때문에, human.readBook(), tiger.hunt()와 같은 메서드는 호출하지 못한다. (가능하게 할려면, Down-Casting이 필요)

다형성을 사용하는 이유?


  • 상속과 메서드 재정의를 활용하여 확장성 있는 프로그램을 만들 수 있음.
  • 그렇지 않는 경우 많은 if-else if  문이 구현되고 코드 유지 보수가 힘듬.
if(grade == "VIP") {
} 
else if (grade == "GOLD") {
} 
else if (grade == "SILVER") {
}
//////
public void forVIPFunc(VipCustomer c) {}
public void forGoldFunc(GoldCustomer c) {}
public void forSilverFunc(Customer c){} ///객체가 추가 될때마다 그 객체 타입에 맞는 메소드를 계속 만들어주어야함... 또는 오버로딩메서드를 추가되는 객체 타입에 맞게 계속 추가..
.
.
.
  • 상위 클래스에서 공통적인 부분을 제공하고 하위 클래스에서 각 클래스에 맞는 기능 구현
  • 여러 클래스르 하나의 타입(상위 클래스)으로 핸들링 할 수 있음.
  • 상위 클래스를 사용하여,  기능이 다른 하위 클래스를 추가하거나 및 확장이 유용.

참조 변수의 형변환


  • 기본형 변수와 같이 참조변수도 형변환이 가능하다. 단, 서로 상속관계에 있는 클래스 사이에서만 가능하다.
  • 자손 타입 -> 조상 타입 (Up-Casting) : 형 변환 생략 가능
  • 조상 타입 -> 자손 타입 (Down-Casting) : 형 변환 생략 불가
Animal human1 = new Human();
Tiger tiger = new Tiger();
Human human2 = null; 
Animal animal1 = null;
human2 = tiger; //에러, human과 tiger 객체는 서로 상속관계가 아니기 때문에.

animal1 = human1; //Up-Casting
human2 = (Human)animal1; //Down-Casting 으로 (Human) 자손타입을 명시해줘야 함. 
  • 형 변환은 단순히 참조변수의 타입을 변환하는 것이지 인스턴스를 변환하는 것은 아니기 때문에 참조변수의 형 변환은 인스턴스에 아무런 영향을 미치지 않는다.
  • 단지 참조변수의 형 변환을 통해서, 참조하고 있는 인스턴스에서 사용할 수 있는 멤버의 범위(개수)를 조절하는 것뿐이다.

instanceof 연산자


  • 참조변수가 참조하고 있는 인스턴스의 실제 타입을 알아보기 위해 사용.
검사하고자 하는 참조변수 instanceof 타입(클래스명) => 연산결과가 맞으면 true, 틀리면 false 를 반환

참조변수와 인스턴의 연결


  • 조상 클래스에 선언된 멤버변수와 같은 이름의 인스턴스변수를 자손 클래스에 중복으로 정의 되었을 때
  • 같은 이름을 같는 메서드는 오버라이딩되서 호출 된다.
  • 같은 이름을 같는 멤버변수의 경우 참조변수의 타입에 따라 달라짐. 즉, 참조 타입의 멤버변수가 사용된다.
class BindingTest {
public static void main(String[] args) { 
        Parent p = new Child(); 
        Child c = new Child(); 
        System.out.println("p.x = " + p.x);   //p.x = 100 
        p.method();                           //Child Method
        System.out.println("c.x = " + c.x);  //c.x = 200
        c.method();                         //Child Method
    }
}

public class Parent { 
    int x = 100; 
    void method() { 
        System.out.println("Parent Method"); 
    } 
}

public class Child extends Parent{ 
    int x = 200; 
    @Override 
    void method() { 
        System.out.println("Child Method"); 
    } 
}
  • 인스턴스변수에 직접 접근(p.x 나 c.x)하면 참조변수의 타입에 따라 사용되는 인스턴스변수가 달라질 수 있으므로 주의 해야한다.
profile
끊임없이 생각하는 주니어 웹 개발자입니다.

0개의 댓글

관련 채용 정보