ABOUT ME

-

Today
-
Yesterday
-
Total
-
  • 다형성, instanceof, 메서드 오버라이딩
    JAVA/개념 - 김영한 강의 2024. 10. 8. 08:02

     

     

    다형성

    • 하나의 객체가 다른 타입으로 사용될 수 있다는 뜻이다.
    • 부모는 자식을 품을 수 있다. 직계 뿐만이 아니라 손자 등 모든 자식 타입을 참조할 수 있다. 이렇게 다양한 형태를 참조할 수 있다고 해서 다형적 참조라 한다.
      • Parent poly = new Parent()
        Parent poly = new Child()
        Parent poly = new Grandson() 

     

     

    캐스팅

    • 업캐스팅(upcasting): 자식 -> 부모 타입으로 변경
    • 다운캐스팅(downcasting): 부모 -> 자식 타입으로 변경

     

     

    다운캐스팅

    public class Parent {
    
    	public void parentMethod() {
        
        	System.out.println("Parent.parentMethod");
        }
    }
    public class Child extends Parent {
    
    	public void childMethod() {
        	System.out.println("Child.childMethod");
        }
    }
    public class PolyMain {
    	public static void main(String[] args) {
        
        // 부모 변수가 부모 인스턴스 참조
        System.out.println("Parent -> Parent");
        
        Parent parent = new Parent();
        parent.parentMetho();
        
        
        // 자식 변수가 자식 인스턴스 참조
        System.out.println("Child -> Child");
        
        child child = new Child();
        child.parentMethod();
        child.childMethod();
        
        
        // 부모 변수가 자식 인스턴스 참조(다형적 참조) 
        System.out.println("Parent -> Child");
        
        Parent poly = new Child(); 
        poly.parentMehod();
        
        //Child child1 = new Parent(); 자식은 부모를 담을 수 없다.
        
     	//자식의 기능은 호출할 수 없다. 컴파일 오류 발생
     	//poly.childMethod();
        
       }
       
     }

     

     

    Parent poly = new Child()

    • 부모 타입의 변수가 자식 인스턴스를 참조한다. 즉, 부모는 자식을 담을 수 있다.
      • 참고로 반대는 불가능하다. Child child1 = new Parent();  // 컴파일 오류 발생
    • Child 인스턴스를 생성했기 때문에 메모리 상에 Child와 Parent 모두 생성된다.
    • poly.parentMehod();  // 생성된 참조값을 Parent 타입의 변수인 poly 에 담아둔다는 뜻이다
    • poly.childMethod();  // 자식의 기능은 호출 할 수 없다!!

     

     

    Child child = (Child) poly  // Parent poly 타입을 Child로 만듦(다운캐스팅)

    • (타입)처럼 괄호에 그 사이에 타입을 지정하면 참조 대상을 특정 타입으로 변경할 수 있다 = 캐스팅
    • 다운캐스팅을 통해 따라서 Parent poly가 일시적으로 Child 타입이 됐다
    • 캐스팅을 한다고해서 Parent poly 타입이 변하는 것은 아니다.  참조값이 Child 타입이 되는것이다
    • child.childMethod()를 호출할 수 있게 되었다. 

     

     

     


    일시적 다운 캐스팅 - 해당 메서드를 호출하는 순간만 다운캐스팅

    public class CastiongMain2 {
    
    	public static void main(String[] args) {
        
        // 부모 변수가 자식 인스턴스 참조(다형적 참조)
        Parent poly = new Child();
        
        ((Child) poly).childMethod();
        
        }
    }

     

     

    이 또한 poly가 Child 타입으로 바뀌는 것이 아니다. 참조값이 Child 타입이 되는 것이다.

     

     

     

     

    업 캐스팅

    //upcasting vs downcasting
    
    public class CastingMain3 {
     	public static void main(String[] args) {
     
     	Child child = new Child();
     	Parent parent1 = (Parent) child; //업캐스팅은 (타입) 생략 가능, 생략 권장
     	Parent parent2 = child; //업캐스팅 생략. 
     
     	parent1.parentMethod();
     	parent2.parentMethod();
     }
    }

     

    • 부모 타입으로 변환하는 경우 (타입)을 생략할 수 있다.

     

     

    A  a = new B() : A로 업케스팅
    B  b = new B() : 자신과 같은 타입
    C  c = new B() : 하위 타입은 대입할 수 없음, 컴파일 오류
    C  c = (C) new B() : 하위 타입으로 강제 다운캐스팅, 하지만 B 인스턴스에 C와 관련된 부분이 없으므로 잘
    못된 캐스팅, ClassCastException 런타임 오류 발생

     

     

     

     

    instanceof

    다양한 대상을 참조하는 다형성이 어떤 인스턴스를 참조하고 있는지 확인하려면 어떻게 해야할까?

    if (객체 instanceof 클래스명) { // 객체가 클래스명 타입인 경우 실행될 코드 }

     

     

     

    ex) Parent는 자신의 인스턴스 혹은 자식의 인스턴스를 참조할 수도 있다. 이를 확인하려면?

     

    public class CastingMain5 {
    
    	public static void main(String[] args) {
        
        	Parent parent1 = new Parent();
            System.out.println("parent1 호출");
            call(parent1);
            
            
            Parent parent2 = new Child();
     		System.out.println("parent2 호출");
     		call(parent2); 
            }
            
            
            private static void call(Parent parent) {
            	parent.parentMethod();
                if(parent instanceof Child) {  // Child 클래스의 parent 인스턴스인가? 즉 parent가 Child를 참조하나?
                	System.out.println("Child 인스턴스 맞음");
                    Child child = (Child) parent;
                    child.childMethod();
                  }
               }
               
    }

     

    실행결과

     

    parent1 호출
    Parent.parentMethod
    parent2 호출
    Parent.parentMethod
    Child 인스턴스 맞음  // parent가 Child클래스의 인스턴스일 경우에만 뜨니까!!  
    Child.childMethod

     

     

     

     

    new Parent() instanceof Parent
    Parent p = new Parent() //같은 타입 true
    
    
    new Child() instanceof Parent
    Parent p = new Child() //부모는 자식을 담을 수 있다. true
    
    
    new Parent() instanceof Child
    
    Child c = new Parent() //자식은 부모를 담을 수 없다. false
    
    
    new Child() instanceof Child
    Child c = new Child() //같은 타입 true

     

     

     

     

     

    메서드 오버라이딩

    • 오버라이딩: 부모 타입에서 정의한 기능을 자식 타입에서 재정의하는 것

     

    다형성에서 메서드 오버라이딩의 핵심은,

    더 하위 자식의 오버라이딩 된 메서드가 항상 우선권을 가진다는 점이다.

    public class Parent {
     	public String value = "parent";
     	public void method() {
     	System.out.println("Parent.method");
     	}
    }

     

    public class Child extends Parent {
     	public String value = "child";
     
     	@Override
     	public void method() {
     	System.out.println("Child.method");
     	}
    }
    public class OverridingMain {
     	public static void main(String[] args) {
     
     
     	//자식 변수가 자식 인스턴스 참조
     	Child child = new Child();
     		System.out.println("Child -> Child");
     		System.out.println("value = " + child.value);
     	child.method();
     
     
     	//부모 변수가 부모 인스턴스 참조
     	Parent parent = new Parent();
     		System.out.println("Parent -> Parent");
     		System.out.println("value = " + parent.value);
     	parent.method();
     
     
     //부모 변수가 자식 인스턴스 참조(다형적 참조) 
     	Parent poly = new Child();
     		System.out.println("Parent -> Child");
     		System.out.println("value = " + poly.value); //변수는 오버라이딩X
     	poly.method(); //메서드 오버라이딩!
     	}
    }

     

     

     

    Parent poly = new Child();

     

     

    • poly 변수는 Parent 타입이다. 따라서 poly.value , poly.method() 를 호출하면 인스턴스의 Parent 타입에서 기능을 찾아서 실행한다.
    • poly.value : Parent 타입에 있는 value 값을 읽는다.
    • poly.method() : Parent 타입에 있는 method() 를 실행하려고 한다. 그런데 하위 타입인 Child.method() 가 오버라이딩 되어 있다. 오버라이딩 된 메서드는 항상 우선권을 가진다. 따라서 Parent.method() 가 아니라 Child.method() 가 실행된다.

     

     

     

     

     

    댓글

Designed by Tistory.