[Java] 상속과 구성
객체지향은 중복코드를 없애기 위해서 존재한다.
객체지향적인 구조를 위해서 일부러 중복코드를 허용하는 경우도 있다.
다형성 = 같은 타입이지만 실행결과가 다양한 객체를 이용할 수 있는 성질. 하나의 타입에 여러 객체를 대입하여 만든다.
상속(Inheritance)
부모클래스를 상속하는 자식클래스는 부모클래스의 기능을 그대로 물려받아 중복코드를 제거할 수 있다.
이후 유지보수가 편해지며 다형성을 구현할 수 있는 장점이 있다.
자식클래스에 메서드를 추가하여 부모클래스의 기능을 확장할 수 있다. extends
키워드 사용
class 오리 {
void 날다();
void 수영하다();
}
class 흰오리 extends 오리{
void 걷다();
}
IS-A 관계
흰오리는 오리이다 처럼 말할 수 있는 관계를 IS-A 관계라고 한다.
이렇게 IS-A 관계(상속관계)에 있을 때 자식 클래스의 객체는 부모 클래스의 자료형인 것처럼 사용할 수 있다.
오리 a오리 = new 흰오리();
메서드 오버라이딩
부모클래스의 메서드를 자식클래스가 동일한 형태로 다시 구현하는 행위 (덮어쓰기)
고무오리
class에 날다
메서드를 다시 구현
class 오리 {
void 날다() { System.out.println("오리가 날개로 날아갑니다."); }
void 수영하다();
}
class 흰오리 extends 오리 {
void 걷다();
}
class 고무오리 extends 오리 {
void 날다() { System.out.println("저는 못 날아요."); } // 메서드 오버라이딩
}
메서드 오버로딩
입력항목이 다른 경우 동일한 이름의 메서드를 만들 수 있다.
class 오리 {
void 날다() { System.out.println("오리가 날개로 날아갑니다."); }
void 수영하다();
}
class 흰오리 extends 오리 {
void 걷다();
}
class 고무오리 extends 오리 {
void 날다() { System.out.println("저는 못 날아요."); }
void 날다(int hp) { System.out.println("hp가 있으면 고무오리도 날 수 있어요."); }
// 메서드 오버로딩. 동일한 날다 메서드지만 int 자료형이 입력항목으로 추가됨.
}
자바는 다중 상속을 지원하지 않는다. 따라서 고무오리
클래스가 오리
와 흰오리
를 같이 상속하는 것은 불가능하다.
상속을 통한 캐스팅(강제형변환) 허용
- 부모 타입에는 모든 자식 객체가 대입될 수 있다.
- 부모 타입으로 자동형변환된 자식객체는 강제형변환을 통해 다시 자식 타입으로 바꿀 수 있다.
- 강제형변환은 자동형변환을 거친 경우에만 사용할 수 있다!
부모 부 = new 부모(); // 가능
부모 부 = new 자식(); // 가능
자식 자 = new 부모(); // 불가능
Animal animal = new Animal();
Dog dog = new Dog();
animal = new Dog() // 자동형변환
dog = (Dog)animal // 강제형변환
상속의 단점
- 상속은 단일 패키지에서 사용해야만 안전하다.
- 하위 클래스는 상위 클래스에 많이 의존하게 된다.
- 상위 클래스의 코드가 수정되면 하위 클래스의 코드도 수정되어야 하는 경우가 많다. (재정의 메소드)
- 확장이라는 목표를 두고 상속을 사용하면 괜찮으나, 해당 설계가 아닌 상황에서 상속을 사용할 시 문제를 발생할 수 있다.
-상속은 캡슐화를 위반한다(하위 클래스가 상위 클래스에 구체적인 구현 내용을 의존하기 있기 때문이다)
구성(Composition)
상속의 취약점을 피하고 싶다면 구성을 사용한다.
구성은 상속과 다르게 Has-A 관계를 가진다.
구성은 하위 클래스가 상위 클래스를 상속받는 것이 아니라 단순히 하위 클래스가 상위 클래스를 private으로 참조받아서 사용하는 것이다.
class 오리 {
void 날기();
void 수영하기();
}
class 흰오리 extends 오리{ // 이미 오리를 상속받아서 로봇오리의 기능은 사용 불가
void 걷기();
소리나기 a소리 = new 소리나기();
void 소리나기(){
a소리.소리나기(); // 구성을 사용하여 로봇오리의 기능 사용하기
}
}
class 로봇오리{
void 소리나기();
}