본문 바로가기

Dev.BackEnd/JAVA

[JAVA] 9. 다형성 / 객체지향적 이해, 다형성과 클래스, 다형성과 인터페이스




Chapter 9. 다형성 (Polymorphism)

다형성의 사전적 정의는 같은 종의 생물이지만 모습이나 특징이 고유한 특징이 다양한 성질을 의미한다.

단어의 뜻부터 어려운 이 다형성이 객체지향개념의 중요한 특징 중 하나이다.


다형성
여러 가지 형태를 가질 수 있는 능력을 의미하며,
자바에서는 한 타입의 참조변수로 여러 타입의 객체를 참조할 수 있도록 함을 구현하는데 사용한다.
좀 더 구체적으로는 조상클래스 타입의 참조변수로 자손클래스의 인스턴스를 참조할 수 있도록 하였다는 것이다.
코드를 통해 이해하는게 더 빠를 것 같다.
class A
{
     public String x() {
          return "x";
     }
}
class B extends A // class A를 상속받고 있는 class B
{
     public String y() {
          return "y";
     }
}

public class Main
{
     public static void(String[] args){
          A obj = new B();
          obj.x();
          obj.y(); // 이 녀석으로 인해 컴파일 에러
     }
}

class B를 obj로 인스턴스화하는데 데이터 타입이 A
실질적으로 class B를 담고 있지만 A인 것.
class A에는 메소드 y가 정의되어 있지 않다.
그래서 obj.y(); // 이 녀석으로 인해 컴파일 에러
어떤 클래스를 인스턴스화 시킬 때, 변수를 담는 데이터 타입은 그 클래스가 될 수도 있고 
그 클래스의 부모 클래스가 될 수도 있다.
도대체 왜 이렇게 객체를 생성하는가 의문이 들 것이다. 다음 코드를 보자.

class A
{
     public String x() {
          return "A.x";
     }
}
class B extends A // class A를 상속받고 있는 class B
{
     public String x() { // 오버라이딩
          return "B.x";
     }
     public String y() {
          return "y";
     }
}

public class Main
{
     public static void(String[] args){
          A obj = new B();
          System.out.println(obj.x()); // 이녀석은 class B에 있는 x가 실행된다.
     }
}
 
A obj = new B();
이 녀석은 class B를 인스턴스화 한 obj 이지만 class A의 행세를 한다.
그 뜻은 class A에 속해 있는 메소드만 호출할 수 있다는 것이다.
즉 class B에만 속해 있는 메소드는 호출할 수 없다.
근데! class B에서 class A에 속해있던 메소드를 오버라이딩했다면
그 오버라이딩한 결과가 호출된다.
아직도 왜 이런 코드를 작성하는지 모르는 건 마찬가지이다.
코드를 하나 더 살펴보자.
class A
{
     public String x() {
          return "A.x";
     }
}
class B extends A // class A를 상속받고 있는 class B
{
     public String x() { // 오버라이딩
          return "B.x";
     }
     public String y() {
          return "y";
     }
}
class B2 extends A
{
     public String x(){
          return "B2.x"
     }
}

public class Main
{
     public static void(String[] args){
          A obj = new B();
          A obj2 = new B2();
          System.out.println(obj.x());
          System.out.println(obj2.x());
     }
}

System.out.println(obj.x()); // 이녀석은 B.x를 리턴한다.
System.out.println(obj2.x()); // 이녀석은 B2.x를 리턴한다.
obj, obj2 둘은 각각 B, B2 클래스를 통해 형성된 것이지만
부모 행세를 하고 있다. 따라서 자식 클래스에서 정의된 메소드를 호출할 수 없고
오버라이딩 한 부분에 대해서만 호출한다.
즉 각각의 자식클래스에서 오버라이딩한 부분이 실행이 된다.

서로 다른 객체가 동일한 데이터 타입으로 존재하면서
각각의 클래스에 정의되어 있는 메소드를 호출할 때 각자가 정의한 대로 호출한다.

이쯤되면 이러한 의문을 갖을 수 있다.
같은 데이터 타입을 갖을 때 장점이 있나?
맞다. 데이터 타입이 같으면 메소드를 실행시키기가 편리해진다.

public static void execute(Calculator cal){
    System.out.println("실행결과");
    cal.run();
}
    public static void main(String[] args) { 
        Calculator c1 = new CalculatorDecoPlus();//다형성
        c1.setOprands(10, 20);
                 
        Calculator c2 = new CalculatorDecoMinus();//다형성
        c2.setOprands(10, 20);
        
        execute(c1);
        execute(c2);
}
위 코드처럼 호출하는 메소드를 만들어두면
하나의 데이터 타입을 대상으로 여러가지를 호출할 수 있다. 


다형성과 인터페이스

Interface I{} class C implements I{} public class PolymorphismDemo2 { public static void main(String[] args) { I obj = new C (); } }

어떤 클래스가 어떤 인터페이스를 구현하고 있다면
그 클래스로부터 인스턴스화 되는 인스턴스의 데이터 타입은 구현하고 있는 인터페이스로 인스턴스화 될 수 있다.

interface I2{
    public String A();
}
interface I3{
    public String B();
}
class D implements I2 , I3{
    public String A(){
        return "A" ;
    }
    public String B(){
        return "B" ;
    }
}
public class PolymorphismDemo3 {
    public static void main( String[] args ) {
        D obj = new D() ;
        I2 objI2 = new D() ;
        I3 objI3 = new D() ;
        
        obj. A() ; // class D가 정의한 모든 멤버를 호출할 수 있다.
        obj. B() ; // class D가 정의한 모든 멤버를 호출할 수 있다.
        
        objI2. A() ; // Interface I2의 데이터 타입이므로 호출 가능.
        //objI2.B(); // Interface I2의 데이터 타입이므로 호출 불가능.
        
        //objI3.A(); // Interface I3의 데이터 타입이므로 호출 불가능.
        objI3. B() ; // Interface I3의 데이터 타입이므로 호출 가능.
    }
}

클래스가 갖고 있는 모든 메소드를 호출해야한다면(모든 기능을 사용해야한다면)
데이터 타입을 그 클래스로 지정해줘야하지만
특정한 인터페이스에 해당하는 기능만을 사용한다고 한다면
데이터 타입으로 그 기능이 속해있는 인터페이스를 데이터 타입으로 하면 된다.
나머지 기능을 마치 존재하지 않는 것처럼 할 수 있다.


포스팅 내용은 생활코딩의 이고잉님의 강의자료를 기준으로 작성하였습니다. 문제가 될 시 삭제하겠습니다.

Chapter 9. The End