Lune Bleue 2019. 12. 17. 01:28

1.다형성이란

여러개의 형태를 갖는다는 의미

상위 타입으로 하위 타입의 객체를 사용 할 수있음

 

  

 부모타입으로 파생된 여러 자식객체를 부모클래스 타입하나로 다룰수 있는 기술  

   ->매개변수타입으로 부모클래스 사용 해서 모든 자식객체를 찾을수 있음 

 

가능한 이유: 주소의 자식안에서 자신을 본다 -> 자신을 상속하는 여러 클래스의 객체 (자식)들을 찾을때 부모클래스 하나로 찾을 수 있다.

 

선언법

부모클래스 객체명(변수) = new 자식클래스(); 

 

부모 클래스의 변수는 자식 클래스의 주소를 담을 수 있다.(업케스팅)

 

      Stack

  객체명(자식의 주소)

  주소의 자식에 있는

    자신을 찾아감

자식객체  : z

 

(부모객체(자신) : x y)

          ->

 

주소에 존재하는 자식이 품고있는 자신(부모객체)를 찾아감 = 부모타입이었던 멤버만 참조가능

-> 자식에 있는 값을 가져오려면 형변환(다운캐스팅) 필요

 


2. 형변환

ㄱ) 업캐스팅 : 상속관계에 있는 부모, 자식 클래스간에 부모타입의 참조형 변수가 모든 자식 타입의 객체주소를 받을 수 있음(묵시적)


ex) Parent p1 = new Child1(); -> 따로 형변환 필요없음(업캐스팅) (parent)new Child();/ 묵시적
     Parent p2 = new Child2();

 

 

ㄴ) 다운캐스팅 : 자식 객체의 주소를 받은 부모 참조형 변수를 가지고 자식의 멤버를 접근해야 할 경우, 부모타입의 참조형 변수를 자식 클래스 타입으로 형 변환 하는것. (명시적)

이렇게 한경우 자식의 변수나 메소드에 접근해야할땐 명시적 형변환 필요(다운캐스팅)


ex)p1.toString(); -> 부모의 toString()...
ex)((Child1)p1).toString(); 자식의 toString().... (참고로 자식에 오버라이딩이 안된걸 쓰면 부모껄 끌고옴) -> 메소드나 값가져올때 ((자식클래스)변수명).메소드()


즉 이렇게 쓴다. (모든 객체의 부모는 Object);
ex) Object o1 = new Parent();  (업캐스팅)
Parent p1 = new Parent();
p1 = (Product)o1 (다운캐스팅)

((Product)o1).toString(다운캐스팅한 메소드 사용)


자식레퍼런스로 부모객체는 사용불가 -> 형변환관련 예외(ClassCast익셉션)

Child c1 = new Parent(); -> 오류

 

객채배열 선언후 자식 클래스를 사용하는 객체를 넣을때 

ex)Parent[] par = new Parent[2]; 
par[0] = new Child1(); 
par[1] = new Child2();

par[2] = new Child3();  

 

메소드의 매개변수로 부모클래스를 넣어 자식 객체를 생성할때

public void create(Parent p){

} -> 매개변수로 Parent참조 변수 를 받음

 

public void exec(){

     create(new Child1());  : Parent p = new Child1()과 같은 의미

     create(new Child2());

     create(new Child3());

}


3.동적바인딩.

오버라이딩으로인해 바인딩이 바뀌는 것.

(모든 메소드는 실행시 메모리에 정적바인딩됨 -> 실행중에 오버라이딩으로 인해 바인딩이 바뀔 경우 동적바인딩)

  -> 부모에 있던것이 정적바인딩 되는데 오버라이딩을 통해 자식의 메소드로 재 바인딩 되는것

 

4. instanceof

현재 참조형 변수가 어떤 클래스 형의 객체 주소를 참조 하고 있는지 확인 할때 사용하는 연산자. 

클래스 타입이 맞으면 true, 맞지 않으면 false 반환

 레퍼런스 instaceof 클래스

 

ex) p1 instanceof Child

 

 

if문과 for문을 사용하여 어떤 클래스의 메소드를 실행 시키고 싶을 때

Parent[] par = new Parent[2]; 
par[0] = new Child1(); 
par[1] = new Child2();

par[1] = new Child3();  

 

for(int i = 0; i< par.length; i++;){

if( par instanceof Child1){

   ((Child1)par).메소드();

}else if(par instanceof Child2){

 ((Child2)par).메소드();

}else if(par instanceof Child3){

 ((Child3)par).메소드();

}
--> 이럴경우 자식의 경우의 수 만큼 if문을 써줘야 되기 때문에 오버라이딩을 통해 한줄로 줄일 수 있다.

for(int i = 0; i< par.length; i++;){

par[i].오버라이딩한메소드()

}

 

 

다단계로 상속한 객체를 찾을 때  
--> 여러개를 상속받은 클래스일 상위클래스부터 써야됨  


ex( 순서 phone<- Smartphone <- Gallaxy 일경우 phone, Smartphone, Gallaxy 순서로 ->이유는 자식은 부모의 모든걸 가지고있음 -> 자식이 위일 경우 부모것인데도 위에서걸려버림) 

 

iif(obj instanceof Phone) {
((Phone)obj).printPhone();
}else if(obj instanceof SmartPhone) {
((SmartPhone)obj).printSmartPhone();
}else if(obj instanceof Gallaxy) {
((Gallaxy)obj).printGallaxy();
}