如果我有一個類中的方法public void send() {//some code}
並且擁有這個類的子對象,也有一個方法public void send() {//some code}
,我如何確保孩子必須在send()方法的某處調用super.send() ?如何確保在孩子中使用超級方法?
我在想這件事,因爲我寫過API,如果在重寫它時沒有調用超類方法,它會拋出一個異常告訴我我沒有調用超類方法。這是硬編碼還是可以用Java中的一些關鍵字來完成?
如果我有一個類中的方法public void send() {//some code}
並且擁有這個類的子對象,也有一個方法public void send() {//some code}
,我如何確保孩子必須在send()方法的某處調用super.send() ?如何確保在孩子中使用超級方法?
我在想這件事,因爲我寫過API,如果在重寫它時沒有調用超類方法,它會拋出一個異常告訴我我沒有調用超類方法。這是硬編碼還是可以用Java中的一些關鍵字來完成?
你真的不能,但你可以...
class MySuperClass {
public final void send() {
preSend();
// do the work...
postSend();
}
protected void preSend() {
// to be overridden in by sub classes
}
protected void postSend() {
// to be overridden in by sub classes
}
}
你不能強制子類調用基類。你可以做的一件事是將你的發送方法改變成一個基本的(最終)「發送」和一個「發送核心」(虛擬),這將被子類覆蓋。基地「發送」會設置一些標誌,說明「sendcore」沒有被調用,然後調用「sendcore」。當它返回時,它可以檢查子「sendcore」是否調用了基類。
Java沒有內建強制調用超類方法。一種方法是在超類中使用私有標誌和委託方法。事情是這樣的:
public class Super {
private boolean inSend;
private boolean superCalled;
public final void send() {
inSend = true;
superCalled = false;
doSend();
inSend = false;
if (!superCalled) {
throw new IllegalStateException("Failed to call super.doSend()");
}
}
protected void doSend() {
if (!inSend) {
throw new IllegalStateException("Cannot call doSend() directly");
}
superCalled = true;
// base class functionality
}
}
沒有關鍵字強制執行這一點。在我看來,你要麼
send
調用本身,或...super
自己撥打send
。我想大多數重寫超類方法的人都會這樣做,如果有足夠的類被抽象出來的話。您可以通過添加一個抽象方法(沒有看到另一種方式)做到這一點:
abstract class MyClass
{
public final void send() // forbid changing this.
{
// do something
doSend():
}
protected abstract doSend(); // no external calls
}
概念上,這就像'委託給一個孩子。爲了達到這個目的,父類應該實現調用抽象方法的最終方法,該方法應該是孩子應該實現的。
abstract class Parent {
public final void invoke() {
// pre invoke code
doInvoke():
// post invoke code
}
protected abstract doInvoke(); // child should implement this
}
http://en.wikipedia.org/wiki/Call_super
什麼你想要做的是一個反模式;你可以做到這一點(許多Java核心類做),但你不應該 - 除非你有一個很好的理由。
除了這一點,這裏提供的所有答案都是正確的。
這就是我一直在尋找的東西。我強烈要求用戶致電父母,但我不知道原因和解決方案。 – farzan 2015-01-19 10:44:51
這對大多數人來說可能更好。但是,您可以使用標誌在運行時強制調用(但沒有編譯時間捕獲)。 – 2011-05-23 04:12:44
我會使preSend()和postSend()爲虛擬。這是因爲如果對象實例化爲: MySuperClass * obj = new ClassDerivedFromMySuperClass(); 這是非常經常使用的方法(例如對於插件),並且不會調用ClassDerivedFromMySuperClass :: preSend()和ClassDerivedFromMySuperClass :: postSend()。 – 2014-06-25 15:59:46
問題與解答關於java – Tom 2014-06-25 16:10:27