2014-01-08 86 views
1

鑑於這種類:我可以告訴抽象方法是否已被調用?

abstract class Foo{ 
    public Foo(){...} 

    public abstract void checkable(); 

    public void calledWhenCheckableIsCalled(){ 
     System.out.println("checkable was called"); 
    } 
} 

是否有任何代碼,我可以把Foo的構造,使calledWhenCheckableIsCalled被調用時checkable叫?

注意:這是對我正在開發的實際項目的簡化。

編輯:我已經實現了模板模式解決方法。我只是想知道是否有另一種方法來做到這一點,我錯過了。 (也許使用反射。)

+2

呃,沒有。 <----> –

+0

@BrianRoach嘆了口氣,我很確定這是行不通的。這將使我想要的功能更容易實現。 – Others

+0

你只知道'checkable()'被調用的方法是在裏面放一些代碼。或者圍繞它創建包裝方法。 – Santosh

回答

4

看起來像是template method pattern

但是,您必須執行Foo.checkable()並引入另一個抽象方法委託給。

abstract class Foo{ 
    public Foo(){} 

    public void checkable(){ 
     calledWhenCheckableIsCalled();    
     doCheckable(); 
    } 

    protected abstract void doCheckable(); 

    public void calledWhenCheckableIsCalled(){ 
     System.out.println("checkable was called"); 
    } 
} 

我還建議作出checkable()最終在這種情況下,這樣你可以肯定的是checkable()不能以另一種方式實現你的預期。

除了布萊恩·羅奇的評論

缺點是受保護的可以在子類擴大到公衆,這樣你就可以沒有明確強制執行。

這是事實,但你可以防止Foo例如,從如果子類增加doCheckable知名度被實例化。因此,只要實例化對象,就必須引入驗證。我建議使用初始化代碼,以便在存在的每個構造函數上執行驗證。然後它不能被忘記調用,因此被繞過。

例如:

abstract class Foo { 
    { // instance initializer code ensures that enforceDoCheckableVisibility 
     // is invoked for every constructor 
     enforceDoCheckableVisibility(); 
    } 
    public Foo() {...} 
    public Foo(Object o) {...} 

    private void enforceDoCheckableVisibility() { 
     Class<?> currentClass = getClass(); 
     while (currentClass != Foo.class) { 
      try { 
       Method doCheckableMethod = currentClass.getDeclaredMethod("doCheckable"); 
       if (Modifier.isPublic(doCheckableMethod.getModifiers())) { 
        throw new RuntimeException("Visibility of " 
            + currentClass.getSimpleName() 
            + ".doCheckable() must not be public"); 
       } 
      } catch (SecurityException | NoSuchMethodException e) {} 
      currentClass = currentClass.getSuperclass(); 
     } 
    } 
} 

由於檢查是使用反射實現的缺點是,它是在運行時僅檢查。所以你當然不會有編譯器支持。但是這種方法可以讓你執行一個Foo的實例,只有當它滿足你的合同時才能存在。

+0

+1 - 這是我在我的評論中得到的。缺點是'protected'可以在子類中擴展爲'public',所以你不能明確地強制執行它。 –

+0

@BrianRoach是的,你是對的。我只能看到一種方法,通過在構造函數中使用反射檢查來防止子類增加可見性。我更新了我的答案。你怎麼看? –

+0

嘿,這當然是一種強制執行的方式:)如果可以的話,我會再次提醒你。 –

0

您無法強制該方法在child中執行。

一個尷尬的建議將從兒童實施知道。我的意思是沒有乾淨的方式AFAIK

2

不,構造函數在對象初始化過程中會被調用一次。然而,你可以得到你的子類,提供了實現調用的方法在超類:

class Bar extends Foo { 

    // implementation of abstract method 
    public void checkable(){ 
     super.calledWhenCheckableIsCalled(); // call to parent's method 
     ... 
    } 
} 

編輯

你可以用方面實現這一目標。使用一個方面,你可以通過引用抽象的父方法來攔截每個方法的調用。這使您不會干擾eith的子代碼。您的calledWhenCheckableIsCalled代碼將成爲攔截代碼的一部分。

abstract class Foo { 

    // use pointcut to intercept here 
    public void checkable(); 
} 
+0

我看到這是如何工作的,但我並不想切換到使用AspectJ。 – Others

+0

+1對於「方面」一點。 – NINCOMPOOP

0
abstract class foo { 

    public abstract void bar(); 

    public void moo() { 
     System.out.println("some code"); 

     this.bar(); 

     System.out.println("more code"); 
    } 
} 

現在如果moo叫的bar底層實現將被使用,它只是從你想要的一個小轉變。

所以你的最終用戶會打電話moo代替bar,但他仍然需要實現bar

0

不,一個抽象的方法沒有體。但是,您可以像這樣鏈接您的方法:

abstract class Foo { 

    void callMeInstead() { 

     // do common 

     callMeImplementation(); 
    } 

    abstract void callMeImplementation(); 
} 
0

它看起來像你對我要尋找的模板模式:

public abstract class Template { 
    public final void checkable() { 
     calledWhenCheckableIsCalled(); 
     doCheckable(); 
    } 

    protected abstract void doCheckable(); 

    private void calledWhenCheckableIsCalled() { 
     System.out.println("checkable was called"); 
    } 
} 

現在,每次checkable()被調用時,calledWhenCheckableIsCalled()也被稱爲。通過實施doCheckable()方法,suclass必須仍然提供checkable()的實際實施。

請注意,使checkable()最終可防止子類重寫它,從而繞過calledWhenCheckableIsCalled()的呼叫。

相關問題