2014-01-08 61 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()的呼叫。

相关问题