상속 관계는 is a(~는 ~이다.) 관계 또는 kind of(~는 ~의 종류이다.) 관계가 되어야 한다.
자식은 부모의 종류 중 하나이다. 그리고 여러 종류의 객체를 하나의 이름으로 부를 수 있는 것을 일반화라고 한다. 예를들어, 버스, 레미콘, 트럭을 자동차라고 부른다면 그것은 일반화시킨 것이다.
상속은 일반화와 확장의 개념을 합한 것이라고 생각하면 된다. 즉, 예를들어, 자동차에 삽을 달아놓는다고 하면 그것은 자동차를 확장시켜서 포크레인을 만든 것이다. 따라서 부모클래스를 상속받는다는 것은 부모가 가지고있는 것을 자식이 물려받아 사용할 수 있다는 것을 의미한다.
아무것도 상속받지 않으면 자동으로 java.lang.Object를 상속받는다. 그렇기 때문에 모든 클래스의 최상위 클래스는 Object가 된고, 모든 클래스는 Object의 자손이다.
왜 참조 타입을 부모 타입으로 사용할까?
부모 타입으로 자손 타입을 참조할 수 있다. 그렇다면 왜 그렇게 사용할까?
Car car = new Bus();
위의 코드를 예시로 보면, 내가 운전하는 것은 버스인데 자동차의 기본 기능만 이용하려고 하면 참조 타입을 부모 타입으로 사용하는 것이다.
즉, 위 코드의 의미는 실제 메모리에 올라간 인스턴스는 Bus이지만, 이 Bus라는 인스턴스를 자동차로만 사용할 것이다라는 의미이다. 따라서 참조 변수 car는 자동차의 액셀, 후진 등의 기능만 사용이 가능하고, 버스 고유의 안내방송 등의 기능은 사용이 불가능하다.
정리하면, 참조 변수의 타입으로 Car를 사용하면 Car가 가지고있는 메서드만 사용 가능하게 되고, 객체를 사용할 때 참조 변수의 타입만 보면 이런 메서드만 사용하겠구나라고 알게되니 코드를 분석할 때 쉬워진다. 하지만 반대로 Bus의 모든 기능을 사용해야 할 경우에는 참조 변수의 타입을 Bus로 해야할 것이다.
다형성 - Method Overriding
부모 클래스가 가진 메서드 시그니처(Method Signature)가 같은 메서드를 자식 클래스가 재정의하는 것이다. 또한 메서드 오버라이딩되면 무조건 자식의 메서드가 실행된다.
public abstract class Car {
public void run() {
System.out.println("전륜구동으로 달리다.");
}
}
public class Bus extends Car{
@Override
public void run() {
System.out.println("후륜구동으로 달리다.");
}
public void 안내방송() {
System.out.println("안내방송하다.");
}
}
public class CarMain {
public static void main(String[] args) {
Bus b1 = new Bus();
b1.run();
b1.안내방송();
Car c1 = new Bus();
c1.run();
}
}
위 코드에서 참조 변수 b1, c1 모두 참조하는 것은 Bus 인스턴스이기에 run 메서드를 실행했을 때, "후륜구동으로 달리다."가 출력된다.
메서드가 Overriding되면 무조건 오버라이딩된 메서드가 실행된다.
정리하면, 참조 타입이 부모 타입이라고 하더라도 실제 동작은 인스턴스에서 Overriding된 기능이 동작하는 것이다.
필드는 Type을 따라가고, 메서드는 Overriding된 자식의 메서드가 실행된다.
단, 필드가 오버라이딩 되어서 자식의 값이 사용된다면 부모 클래스를 만든 사람이 예상하지 못한 결과가 출력될 것이기 때문에 필드는 타입을 따라간다.
객체의 형변환
Bus b2 = (Bus)c1;
위 코드의 의미는 c1이 참조하는 Bus 인스턴스 Bus 타입으로 변환해서 b2가 참조하게 하라는 의미이다.
정보 은닉 (information hiding)
정보 은닉은 객체지향의 중요한 기법이다. 중요한 필드는 은닉하고, 필드는 메서드를 통해서만 접근해서 사용하도록 한다. 즉, 필드를 은닉한다는 것은 외부에서 필드를 직접 접근하지 못하도록 해야한다는 의미이다. 그리고 객체 지향 문법 중 접근 제어자를 사용해서 은닉하게 된다.
여기서 getter/setter를 property라고 하고, setName(), getName() 이면 name property를 가진다고 하는 것이다.
인용
'Language > Java' 카테고리의 다른 글
추상클래스 (0) | 2023.09.15 |
---|---|
super() 생성자와 불변 객체 (0) | 2023.09.14 |
Package (0) | 2023.09.13 |
좋은 객체? 나쁜 객체? (0) | 2023.09.13 |
자바 버전별 메모리 영역과 인스턴스 생성 (0) | 2023.09.13 |