Java

다형성

Sun-Koo 2023. 3. 8. 19:26

하나의 메소드나 클래스가 있을 때 이것들이 다양한 방법으로 동작하는 것


overloading과 다형성

class O{
    public void a(int param){ // int 형 매개변수
        System.out.println("숫자출력");
        System.out.println(param);
    }
    public void a(String param){ // 문자열 매개변수
        System.out.println("문자출력");
        System.out.println(param);
    }
}
public class PolymorphismOverloadingDemo {
    public static void main(String[] args) {
        O o = new O();
        // 오버로딩 
        // 매개변수에 따른 다형성
        o.a(1);
        o.a("one");
    }
}

클래스와 다형성

ex 1)

class A{
    public String x(){return "x";}
}
class B extends A{
    public String y(){return "y";}
}
public class PolymorphismDemo1 {
    public static void main(String[] args) {
        A obj = new B();  // 데이터 타입이 A 인 B인스턴스
        obj.x(); // 클래스 A에 있으므로 실행가능
        obj.y(); // 오류발생 
        //obj가 클래스 A에 행세를 하고 있으므로 y메소드가 존재하지않는다로 간주
        // 데이터 타입은 인스턴스와 동일할 수 있고 부모클래스일 수도 있다
        // A인 것 처럼 동작
    }
}

ex 2)

class A{
    public String x(){return "A.x";}
}
class B extends A{
    public String x(){return "B.x";} // 오버라이딩
    public String y(){return "y";}
}
public class PolymorphismDemo1 {
    public static void main(String[] args) {
        A obj = new B();
        System.out.println(obj.x()); //실행 결과 : B.x
        // 오버라이딩
    }
}

클래스 B를 클래스 A의 데이터 타입으로 인스턴스화 했을 때 클래스 A에 존재하는 맴버만이 클래스 B의 맴버가 된다. 동시에 클래스 B에서 오버라이딩한 맴버의 동작방식은 그대로 유지한다.

 

ex 3)

상속과 오버라이딩 그리고 형변환을 이용한 다형성

class A{
    public String x(){return "A.x";}
}
class B extends A{
    public String x(){return "B.x";}
    public String y(){return "y";}
}
class B2 extends A{
    public String x(){return "B2.x";}
}
public class PolymorphismDemo1 {
    public static void main(String[] args) {
        A obj = new B();
        A obj2 = new B2();
        System.out.println(obj.x());
        System.out.println(obj2.x());
    }
}

ex 4)

abstract class Calculator{
    int left, right;
    public void setOprands(int left, int right){
        this.left = left;
        this.right = right;
    } 
    int _sum() {
        return this.left + this.right;
    }
    public abstract void sum();  
    public abstract void avg();
    public void run(){
        sum();
        avg();
    }
}
class CalculatorDecoPlus extends Calculator {
    public void sum(){
        System.out.println("+ sum :"+_sum());
    }
    public void avg(){
        System.out.println("+ avg :"+(this.left+this.right)/2);
    }
} 
class CalculatorDecoMinus extends Calculator {
    public void sum(){
        System.out.println("- sum :"+_sum());
    }
    public void avg(){
        System.out.println("- avg :"+(this.left+this.right)/2);
    }
} 
public class CalculatorDemo {
    public static void execute(Calculator cal){ //Calculator 매개변수
        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);
    }
}

만약 메소드 execute의 매개변수 데이터 타입이 Calculator가 아니라면 처리가 불가능

이유 : ClaculatorDecoPlus,ClaculatorDecoMinus 둘 중 하나로 하게 된다면 execute(c1) 또는 execute(c2) 둘 중 하나는 오류가 발생하기 때문

 

 하나의 클래스(Calculator)가 다양한 동작 방법(ClaculatorDecoPlus, ClaculatorDecoMinus)을 가지고 있는데 이것을

다형성이라고 한다 !!!!


인터페이스와 다형성

인터페이스를 구현하고 있는 클래스가 있을 때 이 클래스의 데이터 타입으로 인터페이스를 지정 할 수 있다

ex 1)

interface I{}
class C implements I{}
public class PolymorphismDemo2 {
    public static void main(String[] args) {
        I obj = new C();
        // C의 데이터 타입으로 인터페이스 I가 될 수 있다
    }
}

다중 상속이 지원되는 인터페이스의 특징과 결합해서 상속과는 다른 양상의 효과

ex 2)

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(); // A
        obj.B(); // B
         
        objI2.A();  // A
        //objI2.B(); I2에는 B메소드가 없음 에러
        //bjI2의 데이터 타입이 인터페이스 I이기 때문이다. 인터페이스 I는 메소드 A만을 정의
        
        //objI3.A(); I3에는 A메소드가 없음 에러
        objI3.B(); // B
    }
}

인스턴스 objI2의 데이터 타입을 I2로 한다는 것은 인스턴스를 외부에서 제어할 수 있는 조작 장치를 인스턴스 I2의 맴버로 제한한다는 의미가 된다. 인스턴스 I2와 I3로 인해서 하나의 클래스가 다양한 형태를 띄게 되는 것이다.

 

 

ex 3)

// Steve : 아빠, 프로그래머, 신도
// Rachel : 엄마, 프로그래머
// 회사 입장에서는 둘다 프로그래머만 본다.
// 회사의 관점

interface father{}
interface mother{}
interface programmer{
    public void coding();
}
interface believer{}
class Steve implements father, programmer, believer{
    // 오버라이딩
    public void coding(){
        System.out.println("fast");
    }
}
class Rachel implements mother, programmer{
    // 오버라이딩
    public void coding(){
        System.out.println("elegance");
    }
}
public class Workspace{
    public static void main(String[] args){
        programmer employee1 = new Steve();
        programmer employee2 = new Rachel();
         
        employee1.coding(); // fast
        employee2.coding(); // elegance
    }
}