클래스의 행위(동적) 정보에 맞춰 클래스를 설계 (상속) 하는 방법에 대해 알아보자
수평적 구조는 중복 발생, 유지보수의 여러움, 확장성 떨어짐 과 같은 많은 문제가 있다.
->그래서 수직적 구조를 쓴다. 부모가 중복 부분을 만들고, 자식들은 상속 받으면 된다.
부모와 자식을 연결해 부모를 이용, 자식을 동작시킬 수 있는 원리로 클래스를 설계 해야한다.
자식 클래스를 숨기고 바깥쪽에 있는 부모로 자식을 동작 시킬 수 있는 방법 -> 상속
상속 구조를 왜 쓸까?
- 코드 중복 최소화, 메서드 재활용
부모 클래스를 통제하면 자식들도 통제된다. 부모에 의해 자식들의 동작 방법이 달라진다.
Dog 클래스 사용 시 만든 사람은 동작구조를 알지만 사용하는 사람은 모른다.
왜? 소스코드를 노출시키지 않기 때문 - 다른 클래스에 의해 Dog 을 동작시킨다
Dog과 동작 시키는 클래스를 세트로 만들 필요가 있다.
어떤 클래스가 중요해 노출시키고 싶지 않다면, 리모콘 같은 클래스가 필요하다
TV = 자식, 리모콘 = 부모
부모가 명령하고 자식은 실행한다.
Tv안 구성 요소를 알 필요는 없다. 리모콘 사용 방법만 알면 된다.
?class 가 Animal class 이다. Animal class를 구동하면 Dog을 이용할 수 있게 해야한다.
Animal과 Dog은 상속관계이다. 자식을 노출시키지 않고 부모를 사용해 자식 이용이 가능하다.
Dog을 다른 사람에게 주고싶다? -> animal과 상속관계를 해 배포해야한다.
Dog을 쓰려면 객체 생성을 해야한다.
Dog d = new Dog(); //이것은 바람직하지 않다. dog의 동작방식을 모를 때 d.를 한다면 dog에 어떤 메서드가 있는지 모른다.
그래서 Animal을 써야한다. 이것을 Upcasting 라고 한다.
부모를 통해 자식을 구동하는 방법이다.
객체 생성은 자식이 하고 (Dog), 부모가 받는다(Animal)
Animal ani = new Dog();
부모는 큰 타입이고 자식은 작은 타입이기 때문에 받을 수 있다. 상속관계이기 때문에 가능하다.
dog이 animal을 상속 받으면 dog+ animal 사용 가능하다.
ani는 부모 클래스의 eat()을 사용할 수 있다.
업캐스팅으로 만든 것은 부모의 eat에는 접근 가능하나, 자식의 eat에는 접근이 불가능하다.
업캐스팅을 부모 타입으로 받기 때문에 ani는 부모 메모리에만 접근 할 수 있다.
업캐스팅으로 만들어진 것은 어떻게 자식 메서드를 쓸 수 있을까?
상속 체이닝과 super
상속 체이닝? 상속이 되어 온 족보.. 최상위 클래스인 Object class까지 올라간다.
자식 생성 전, 부모가 생성 되어야한다 super()을 통해 부모 먼저 생성시킨다.
자식은 부모의부모의부모의.. 것까지 쓸 수 있다.
부모, 자식에게 eat() 이 있다면
부모가 가진 것을 자식이 물려받아 자식에게 맞게 재정의를 해야한다
-> Override
ani는 재정의 된 것이 있는지 둘러본다. 자식이 재정의를 했다면 자식의 eat()이 실행된다
부모의 eat()을 컴파일 했는데 자식의 eat()이 구동된다. 실행해봐야 알 수 있다
-> 이것을 동적바인딩 이라고 한다.
컴파일 시점에선 모른다. 런타임 즉, 실행해봐야 누구의 것인지 안다.
super();는 생성자 문장의 가장 첫 문장에서 실행해야 한다 (= first statement)
public class Dog extends Animal{
public Dog(){
int a=10; //수행문.
super(); //new Animal()이 호출됨.
}
이러면 안된다는 소리. int a=10;은 super뒤로 와야한다.
메서드 재정의override란
부모에게 받은 것이 자식에게 부적합하다. -> 부모의 eat()을 재정의한다. 나에게 맞게 수선한다.
POV:
1. 컴파일 시점엔 부모의 것
2. 실행 되면 자식의 것,
jvm이 부모의 eat을 찾아간다. 재정의가 되어있다면 자식의 eat을 구동한다.
Animal을 가지고 Dog의 eat을 구동시킨다 -> 동적바인딩
실행 시점에서 사용될 메서드가 결정된다. 누구의 eat인지 실행 전까지는 모른다.
Dog, cat 클래스의 eat 을 재정의 한다.
public void eat(){ //override,재정의
System.out.println("dog: eat");
}
public void eat(){
System.out.println("cat: eat");
}
public class OverrideTest {
public static void main(String[] args) {
Animal ani = new Dog(); //upcasting
//왜?하지: dog의 class파일만 있을 시, dog를 가지고 구동하기엔 무리
// animal이라는 클래스가 dog와 상속관계일때,
ani.eat(); //컴파일전 animal의 것, 실행 시 Dog의 것이 됨 -> 동적바인딩
ani =new Cat();
ani.eat();
}
}
업캐스팅 : Animal ani = new Dog();
부모를 통해 자식을 구동하고 싶을 때,
public void eat(){
System.out.println("동물 : eat");
}
부모 클래스도 eat이라는 메서드가 있지만, 자식의 eat메서드가 실행된다.
왜? 자식이 재정의, override 해놨기 때문에.
'JAVA > Bootcamp 자바' 카테고리의 다른 글
자바 - 다형성 (0) | 2024.02.29 |
---|---|
Downcasting, 객체형변환 (0) | 2024.02.28 |
부모, 자식, 상속, protected, extends (0) | 2024.02.27 |
class, object, instance (0) | 2024.02.26 |
JVM의 메모리영역, 객체 생성과 static (1) | 2024.02.26 |