public class Car{
private final String name;
Car(String name) {
this.name = name;
}
public final String getName() {
return name;
}
}
public class Avante extends Car{
Avante(String name) {
super(name);
}
public void print() {
System.out.println(getName());
}
}
현재와 같이 부모 객체(Car)의 멤버변수가 private이고 메서드가 public final로 되어있는 상태에서도, 상속때문에 캡슐화가 깨졌다고 볼 수 있는건가?
→ 그렇지않다.현재 부모객체의 것들을 자식객체가 변경하지 못한다 (final 메소드는 재정의를 막는다)
캡슐화는 어떻게
(상태) 를 가리는 방법을 의미한다. (메시지는 어떻게
가 아니라 무엇을
을 표현한다.)
상속을 했다고 캡슐화가 깨지는게 아니고, 구현을 잘못하면 상속을하든 상속을 하지 않든 캡슐화가 깨진다.
( 메소드명에 상태가 노출(컬렉션을 sort를 할때 범용성에 맞게 sort()라 하는 게 아닌 , bubbleSort()이런식으로 미리 정의하는 것도 상태를 노출하는 것이다 )되도 캡슐화를 위반했다고 할 수 있다.)
객체지향의 특징엔 상속, 캡슐화, 다형성, 추상화가 있다.
상속을 하면 캡슐화가 깨진다는 말은 이상하다.
왜냐면, 같은 목표와 지향점(OOP)을 바라보는 개념이 서로 상반되는게 말이 안된다.
결국, 캡슐화가 깨지는 것은 개발자가 어떻게 사용하는지에 따라 달렸다.
자식 객체가 부모객체의 멤버변수를 그대로 사용하거나, 메소드를 재정의해서 사용하는 경우
부모 객체의 캡슐화가 깨지게 된다.
proteced final someMethod(), public final someMethod()
이와 같은 메소드가 부모객체에 있고, 자식객체가 부모객체의 이러한 메소드를 가져다 쓰는 경우는 캡슐화를 위반한 것이 아니다.
그럼 상속은 도대체 언제???
클래스의 행동을 확장(extend)하는 것이 아니라
정제(refine)할 때
사용한다.
확장이란, 새로운 행동을 덧붙여 기존의 행동을 부분적으로 보완하는 것을 의미
하고,
정제란, 부분적으로 불완전한 행동을 완전하게 만드는 것을 의미
한다.
확장
public class Numbers extends HashSet<Number> {
private int addCount = 0;
@Override
public boolean addAll(final Collection<? extends Number> c) {
addCount += c.size();
return super.addAll(c);
}
}
부모객체의 메소드를 재정의하며 기능을 확장했다.
정제
public abstract class Adder{
abstract int add(int target);
}
public class Number extends Adder{
private final int value;
Number(int value) {
this.value = value;
}
@Override
int add(int target) {
return value + target;
}
}
추상클래스(미완성 클래스)를 이용
하여 Adder의 미안성 메소드 add()를 Number 재정의하여 완성
한다.
이때 정제되었다고 한다.
댓글