Java 클래스 final
에서이 메소드를 대체 할 수 없음을 표시 하기 위해 메소드를로 정의 할 수 있습니다 .
public class Thingy {
public Thingy() { ... }
public int operationA() {...}
/** this method does @return That and is final. */
public final int getThat() { ...}
}
분명합니다. 우연한 재정의 또는 성능 저하로부터 보호하는 데 유용 할 수 있습니다. 그러나 그것은 제 질문이 아닙니다.
내 질문은 : OOP 관점 final
에서 클래스 디자이너 가 메소드를 정의 함으로써이 메소드가 항상 설명 된대로 또는 암시 적으로 작동 할 것이라고 약속 했습니다. 그러나 종종 방법이 수행하는 것이 더 복잡하고 속성을 제공하는 것보다 복잡한 경우 클래스 작성자의 영향을받지 않을 수 있습니다 .
구문상의 제약은 나에게 분명하지만 OOP의 의미는 무엇입니까? 되어 final
대부분의 클래스 저자에 의해 이러한 의미에서 올바르게 사용?
방법은 어떤 종류의 “계약”을 final
약속합니까?
답변
언급했듯이 final
Java 메소드와 함께 사용하여 메소드를 대체 (객체 범위)하거나 숨길 수 없음 (정적)을 표시합니다. 이를 통해 원래 개발자는 서브 클래스로 변경할 수없는 기능을 작성할 수 있으며 이것이 제공하는 모든 보증입니다.
즉,이 방법이 비공개 필드 / 방법과 같은 다른 사용자 정의 가능한 구성 요소에 의존하는 경우 최종 방법의 기능은 여전히 사용자 정의 할 수 있습니다. 이것은 (다형성과 함께) 부분적인 커스터마이징이 가능하지만 좋습니다.
다음을 포함하여 무언가를 사용자 정의 할 수 없게하는 데는 여러 가지 이유가 있습니다.
-
성능 -일부 컴파일러는 작업, 특히 부작용이없는 작업을 분석하고 최적화 할 수 있습니다.
-
캡슐화 된 데이터 확보 -생성시 속성이 설정되어 절대로 변경해서는 안되는 불변 개체를 살펴보십시오. 또는 해당 속성에서 파생 된 계산 된 값입니다. 좋은 예는 Java
String
클래스입니다. -
신뢰성 및 계약은 – 객체는 프리미티브 (구성된다
int
,char
,double
, 등) 및 / 또는 기타 객체. 이러한 구성 요소에 적용 가능한 모든 작업이 더 큰 개체에서 사용될 때 적용 가능하거나 논리적이어야하는 것은 아닙니다.final
수정자를 사용한 메소드를 사용하여이를 확인할 수 있습니다. 카운터 클래스가 좋은 예입니다.
public class Counter {
private int counter = 0;
public final int count() {
return counter++;
}
public final int reset() {
return (counter = 0);
}
}
public final int count()
메소드가 아닌 경우 final
다음과 같이 할 수 있습니다.
Counter c = new Counter() {
public int count() {
super.count();
return super.count();
}
}
c.count(); // now count 2
또는 이와 같은 것 :
Counter c = new Counter() {
public int count() {
int lastCount = 0;
for (int i = super.count(); --i >= 0; ) {
lastCount = super.count();
}
return lastCount;
}
}
c.count(); // Now double count
답변
최종 방법은 어떤 종류의 “계약”을 약속합니까?
다른 방법으로 보아라. 최종이 아닌 메소드는 자신의 구현으로 재정의 할 수 있으며 클래스가 여전히 예상대로 작동 한다는 것을 암시 적으로 보장 합니다. 클래스가 메소드 덮어 쓰기를 지원한다고 보장 할 수없는 경우 최종 메소드로 만들어야합니다.
답변
우선, 비추 상 클래스 final
와 필드 및 메소드를 표시 할 수 있습니다 . 이런 식으로 전체 클래스를 서브 클래 싱 할 수 없습니다. 따라서 수업의 행동이 고정됩니다.
final
최종 메소드가 비 최종 메소드를 호출하는 경우 표시 메소드가 서브 클래스에서 동일한 동작을 보장하지는 않는다는 데 동의합니다 . 행동이 실제로 고쳐 져야한다면, 이것은 관습과 신중한 디자인에 의해 달성되어야합니다. 그리고 이것을 javadoc에서 이것을 잊지 마십시오! (Java documentation)
마지막으로 final
키워드는 JMM (Java Memory Model)에서 매우 중요한 역할을합니다. JMM은 final
필드의 가시성을 달성하기 위해 적절한 동기화가 필요하지 않음 을 보장 합니다. 예 :
class A implements Runnable {
final String caption = "Some caption";
void run() {
// no need to synchronize here to see proper value of final field..
System.out.println(caption);
}
}
답변
“최종”의 사용과 이것이 소프트웨어의 전체 설계 계약에 미치는 영향에 대해 어떤 주장을 할 수 있는지 잘 모르겠습니다. 개발자는이 방법을 무시하고 계약을 무효화 할 수 없습니다. 그러나 다른 한편으로, final 메소드는 서브 클래스에 의해 값이 설정되는 클래스 또는 인스턴스 변수에 의존 할 수 있으며 재정의 된 다른 클래스 메소드를 호출 할 수 있습니다 . 따라서 final은 기껏해야 매우 약한 보증입니다.
답변
아니요, 수업 저자의 영향을받지 않습니다. 파생 클래스에서는 재정의 할 수 없으므로 기본 클래스 작성자가 의도 한대로 수행됩니다.
http://download.oracle.com/javase/tutorial/java/IandI/final.html
주목할만한 점은 생성자에서 호출 된 메소드가 있어야 함을 제안하는 부분 final
입니다.