상위 및 하위 클래스 간의 추상화 장벽 교차 - [OOP 및 Java #15]
10300 단어 javaoopcomputerscienceprogramming
동기 부여
이 기사는 프로그래밍 방법론 수업에서 받은 질문에서 영감을 받았습니다. 프로그래밍 실습을 풀기 위해 Java 코드를 작성하는 이 클래스에서는 클래스의 모든 속성이
private
및 final
여야 한다는 제약 조건이 있습니다. 이는 클래스 외부의 필드에 대한 액세스가 없으며 이 필드가 초기화되면 수정이 허용되지 않음을 의미합니다. 이 엄격한 요구 사항은 Java에서 클래스 개체를 구성할 때 불변성을 적용하기 위해 적용됩니다.조만간 실습이 더 복잡해지면 상속의 도움으로 여러 클래스를 구성하고 구성하는 OOP 솔루션으로 이동하는 경향이 있습니다. 그런 다음 하위 클래스에서 상위 클래스의 이 필드
private final
에 액세스해야 할 때 문제가 발생합니다. 그러면 우리는 무엇을 해야 합니까?구체적인 예를 들기 위해 다음과 같은 클래스가 있다고 가정해 보겠습니다.
class Parent {
private final int value;
Parent(int value) {
this.value = value;
}
}
class Child extends Parent {
Child(int value) {
super(value);
}
int add(int another) {
return super.value + another; // UNABLE TO ACCESS!
}
}
자식 클래스가 부모 클래스에서
value
에 액세스하려면 어떻게 해야 합니까?솔루션
수정자 변경
이를 처리하는 가장 간단한 방법은 액세스 한정자를
private
에서 다른 것으로 변경하는 것입니다. 아마도 public
또는 protected
일 것입니다. 이 솔루션은 상황에 따라 합법적일 수 있습니다. 경우에 따라 이 값을 다른 클래스에 노출하는 것이 완전히 정상일 수 있습니다.getter 메서드 추가
inheritance에 대한 Oracle의 Java 자습서에서
A subclass does not inherit the
private
members of its parent class. However, if the superclass has public or protected methods for accessing its private fields, these can also be used by the subclass.
따라서 가능한 또 다른 해결책은 부모 클래스에 getter 메서드를 갖고 해당 메서드를 공개하는 것입니다. 이렇게 하면 하위 클래스(및 기술적으로는 다른 클래스)가 getter를 통해 액세스할 수 있습니다. 간단한 예는 다음과 같습니다.
class Parent {
private final int value;
Parent(int value) {
this.value = value;
}
public int getValue() {
return this.value;
}
}
class Child extends Parent {
Child(int value) {
super(value);
}
int add(int another) {
return super.getValue() + another; // CAN ACCESS!
}
}
이제 "비공개"필드가 노출되더라도 여전히 하나의 추상화 계층이 있다는 점에서 getter 메서드를 갖는 것이 유리할 수 있습니다. getter 메서드의 사용자는 해당 값이 생성되는 방식을 알 필요가 없습니다. 이 값은 getter 메서드의 일부 복잡한 사전 처리 단계에서 조작할 수 있습니다(필요한 경우). 또한 기본 개인 필드가 크게 변경될 수 있지만 getter 메서드의 사용자는 인식하지 못합니다.
코드 설계 재고
마지막으로, 이 문제는
private final
필드에 액세스해야 하는 합법적인 필요성이 있는지 재고해야 한다는 신호일 수 있습니다. 부모-자식 관계가 주어지면 어떤 필드/메소드가 어떤 클래스에 상주해야 하는지 명확하지 않은 경우가 있습니다.더 나은 코드 디자인은 비공개 최종 필드가 그대로 유지되어 부모 클래스와 자식 클래스 사이에 추상화 장벽을 유지하도록 제안할 수 있습니다. 한 가지 예시 솔루션은 다음과 같습니다.
class Parent {
private final int value;
Parent(int value) {
this.value = value;
}
int add(int another) {
return this.value + another;
}
}
class Child extends Parent {
Child(int value) {
super(value);
}
int add(int another) { // will work if this method is omitted as well,
return super.add(another); // as it will be inherited
}
}
안티 패턴
일부 사람들이 생각할 수 있는 문제 해결 방법은 자식 클래스에서 동일한 필드를 다시 선언하는 것입니다.
class Parent {
private final int value;
Parent(int value) {
this.value = value;
}
}
class Child extends Parent {
private final int value;
Child(int value) {
super(value);
this.value = value;
}
int add(int another) {
return this.value + another; // will work but not recommended
}
}
이것은 작동하지만 공유 속성 간의 중복을 줄이기 위해 상속을 사용하지 않기 때문에 틀림없이 나쁜 디자인입니다. 또한 특히 이러한 필드가
final
로 선언되지 않은 경우 값(동일한 것을 나타내는 의미)이 동기화되지 않을 수 있습니다.결론
동기를 부여하는 질문을 받았을 때 저의 즉각적인 대답은 "공개 getter 메서드를 만드십시오"였습니다. 그런 다음 후속 질문을 받았습니다.
생각하게되었습니다.
이 기사는 "왜"라는 질문을 더 자주 하고 대답의 이유를 탐구하도록 상기시켜 줍니다.
Reference
이 문제에 관하여(상위 및 하위 클래스 간의 추상화 장벽 교차 - [OOP 및 Java #15]), 우리는 이곳에서 더 많은 자료를 발견하고 링크를 클릭하여 보았다 https://dev.to/tlylt/crossing-abstraction-barrier-between-parent-child-class-oop-java-15-48d8텍스트를 자유롭게 공유하거나 복사할 수 있습니다.하지만 이 문서의 URL은 참조 URL로 남겨 두십시오.
우수한 개발자 콘텐츠 발견에 전념 (Collection and Share based on the CC Protocol.)