Kim-Baek 개발자 이야기

자바 기본 (16) - 상속, 다형성 본문

개발/java basic

자바 기본 (16) - 상속, 다형성

김백개발자 2020. 10. 7. 02:43
예전에 자바를 처음 공부하던 때, 네이버 블로그에 정리한 내용을 이제 티스토리로 옮기고자 한다

◎ super 

- 부모객체를 의미한다.   this 는 (현재)이 객체
- super.부모객체의 멤버 -> 부모객체의 instance 변수/메소드 호출시 사용
     ※ super . 는 생략하더라도 보통 컴파일러가 알아서 처리!
- ★ super( [값, ...] ) -> 부모객체의 생성자 호출
    -> 생성자 구현부의 첫 구문으로 와야한다 (this(), super()는 같이 올 수 없어!)
    -> 생성자 구현부에 this () 나 super 가 없으면 super(); 가 첫 구문으로 들어가게 된다

 public A( ){
                   <- super(); 를 컴파일러가 넣어준다.
}                         ※ default 생성자가 할일이 생겼다! -> super(); 부르기
-> 상위 클래스의 객체를 자동으로 만들어서 같이 묶어서 사용할 수 있도록 하기위해서.

 

public class super{
   super( int i ) { }
 }                                        <- super(){ } 를 넣으면 오류가 안난다.

public class A extends super{

} 
-> 에러가 난다. super 에 no arguement 생성자가 없어서이다. 기본적으로 no arguement 생성자를 만들어 주는 것이 좋다. (특히 VO 클래스)

 


◎ 메소드 오버라이딩 (Overriding)


- 부모클래스의 메소드를 자식 class 에서 (구현을) 재 정의 하는 것 (리턴타입, arguement 바꾸는 것 X) -> 재 구현
- 부모 class는 모든 자식 class 들에 적용될 구현만 가능 -> 메소드 구현이 추상적일 수 있다. 이것을 하위 class 에서 자신의 특징에 맞도록 재구현(구체화) 하도록 하는 것.
- 부모 클래스만 보고도 메소드를 사용할 수 있도록 하기위해서이다.

선언문 관련 규칙
1. 메소드 이름, 매개변수, 리턴 타입이 같아야한다
2. 부모의 접근제한자와 같거나 더 넓은 범위를 가진다. (private<package friendly<protected<public)
    -> private 메소드는 안된다 (각각 따로 사용하기 때문이다)
3. 부모가 throws 한 exception만 throws 할 수 있다



◎ final ( 제한자)

 - 마지막, 변경이 안된다는 뜻
변수 : 상수가 된다. -> static , instance, local 모두 가능
메소드 : overriding 을 하위 class 에서 할 수 없는 메소드
class : 상속할 수 없는 class


◎ 접근 제한자


- private : 같은 클래스내에서만 접근 가능 , 키워드 : private , UML : -
- package friendly (default) : 같은 package 내에서만 접근 가능 - 접근 제한자도 없고 UML도 없기 때문에 default 라 불린다 -> 아무 표시도 안하게 되면 package friendly 이다.
- protected : 상속 관계일 경우 하위 class 에서 super를 이용해 접근가능 -> 패키지 무관
                    -> 상속이 아닐경우에는 package friendly 와 동일하다. 키워드 : protected, UML : #
ex)

-> 만약 상속관계라면 super.go()를 통해서 다른 패키지일지라도 접근이 가능하다. : 패키지와 무관
-public : 어디는 접근이 가능하다. 키워드 : public , UML : +


◎ 다형성 (Polymorphisom)


- 부모 type 변수( reference type ) = 자식 (자손) 객체     + overriding

※ 다형성에서의 실행 구조

Animal a = new Animal();
Animal b = new Dog();
Animal c = new Cat();
   -> c.eat(); 는 실행이 가능하나 , c.Cry(); 는 컴파일이 안된다.

-> c.Cry 도 실행시점에서는 가능한 코드이다. 하지만 컴파일러는 c.Cry() 라고 하면 값을 통해서 찾는 것이 아니라 c 의 타입인 Animal 에서 찾게 된다. 따라서 cry()를 찾지 못한다는 에러가 나오게 된다. c.Eat 의 경우도 컴파일시 : Animal -> 변수 Type 에서 확인  실행 : Cat -> 실제객체에서 실행 (Cat 객체에 eat 메소드가 있으니 오버라이딩 된 것을 실행한다. 없으면 super를 통해 올라감)
   ※ 컴파일은 그냥 확인하는 것이다 ! 되는지 안되는지. 컴파일러는 똑똑하지 않다!

※ 다형성 => 부모의 메소드만 사용해라! (오버라이딩해서)
Animal c= new cat();
Cat a = (cat) c ;         <- 레퍼런스 타입은 형변환시 primitive 타입처럼 데이터가 잘리거나 변화하지 않고 타입만 변화한다
a.Cry() 는 사용이 가능하다

◎다형성 사용의 장점? 어떤 상황에서 다형성을 사용하는가.
1. 배열에 적용

Animal [] a = new Animal [10];                            a : A[  ] ,    a[ i ] = A
a[0] = new Animal();
a[1] = new Cat();                         ※ 부모타입의 객체를 배열로 쓰면 자식타입은 모두 들어갈 수 있다.
a[2] = new Dog();
-> for (int i = 0; i<a.length; i++)
{
        a[ i ].eat;                             결과 : 먹다 -> 생선먹다 -> 사료먹다
}



=> 만약 다형성을 못쓰면 개의 배열, 고양이의 배열, 각자의 배열을 따로 만들었어야할 것이다. 하나의 매니저를 통해 다양한 자식 객체(개, 고양이)들의 관리가 가능해진다. 다른 타입이 추가가 되더라도 동물의 상속만 받는다면 이 매니저에서 관리가 가능- 확장성 ↑

public void feed (Animal a){
  a.eat();
  a.sleep();
}
Cat c = new cat() -> feed(c) 가능
Dog d = new dog() ->feed(d) 가능

=> 만약 다형성을 모른다면?
public void feed(Cat c){ }
public void feed(Dog d){ }        -> 오버로딩 메소드를 만들어야 한다.

 

※ 이클립스의 사용
- source -> constructor 눌러서 super 클래스의 생성자를 고를수 있다.
- super . 을 쓰는 경우는 오버라이딩 한 하위 메소드에서 원본의 메소드를 부를 때 가장 많이 사용
- genenrate constructor from super class -> 인스턴스 변수가 없을때
- ctrl + d 한줄 지우기
- 주석에 //TODO ---- 할일 써놓기 해두면 화면 오른쪽에 파란색으로 표시가 된다.
- 객체 instanceof Type -> 객체가 Type 의 객체냐? : boolean
   * 객체와 Type이 상속관계일때만 사용가능

 

반응형
Comments