2016-12-01 110 views
0

我在Java中有抽象類。我想用反射調用他的子類(如果存在的話)的具體方法。未知子類的調用方法

public abstract class Parent { 
    public void doIt(String functionName) { 
     if (the caller class have method called as functionName parameter) { 
      call it 
     } 
    } 
} 

public class Child extends Parent{ 
    public void spacialMethod() { 
     System.out.println("Child special method called"); 
    } 
} 

public class Child2 extends Parent{ 
    // Empty 
} 

所以,如果我將運行該代碼:

Child child = new Child(); 
child.doIt("spacialMethod"); // Will print the text 
Child2 child2 = new Child2(); 
child2.doIt("spacialMethod"); // Nothing will happened 

我怎樣才能在父類檢查當前的子類都被稱爲「specialMethod」的方法?

+3

爲什麼?爲什麼不在抽象類中定義一個「什麼都不做」的版本,然後調用它,如果子類覆蓋它,它們的版本會被調用? –

回答

5

這是可能做你已經問過的問題(看答案的結尾),但如果沒有很好的理由,這是糟糕的設計。

如果您不需要在運行時確定名稱,我將Parent中的方法定義爲什麼都不做,然後調用它;如果子類覆蓋它,那麼很好。

public abstract class Parent { 
    public void doIt() { 
     this.specialMethod(); 
    } 
    public void spacialMethod() { 
     // Do nothing 
    } 
} 

public class Child extends Parent{ 
    @Override 
    public void spacialMethod() { 
     // Optionally call super.specialMethod() here 
     System.out.println("Child special method called"); 
    } 
} 

public class Child2 extends Parent{ 
    // Empty 
} 

但如果你真的想與反思這樣做(比如,你需要定義在運行時的名字),它並不難:

// Not recommended if you can avoid it 
public void doIt() { 
    try { 
     this.getClass().getMethod("specialMethod").invoke(this); 
    } 
    catch (/*...appropriate exception handling...*/) { 
    } 
} 
+0

我不想在父級創建「default」'spacialMethod',因爲我不知道方法名是什麼,我只能在運行時找到它...劑量this.getClass()。如果我沒有在'Parent'類聲明它,getMethod(「specialMethod」)'會工作嗎? – nrofis

+1

@nrofis然後你有一個糟糕的設計。 –

+0

@nrofis:是的。這是一種替代方案,不是前面代碼塊的擴展。 'this.getClass()'獲取實例的類,其中(在子類中)是子類。 –

0

除了從TJ克勞德你答案可以使用getDeclaredMethods來獲取所有方法並調用專用之一。

public void doIt() { 
     Method[] methods = getClass().getDeclaredMethods(); 
     for(Method method : methods){ 
      if(method.getName().contains("special"){ 
      method.invoke(this); 
      } 
     } 
    } 
+1

只是爲了記住'getDeclaredMethods'不返回繼承的方法,也就是說,超類中聲明的方法不會被返回。 –

0

就沒有反思的例子:

有某種這是每個子類中具體實現或不實現「訪問」的;在實施時,它會委託給孩子所需的方法。

請注意,與下面的示例不同,訪問器實現可以在類本身的外部,以便孩子甚至不必知道它將如何訪問。

public interface SpecialOpAccessor { 
    void doIt(); 
} 

public abstract class Parent { 
    protected SpecialOpAccessor accessor; 

    public void doIt() { 
     if (accessor != null) { 
     accessor.doIt(); 
     } 
    } 
} 

public class Child extends Parent{ 

    public Child() { 
     super(); 
     this.accessor = new SpecialOpAccessor() { 
     @Override 
     public void doIt() { 
      Child.this.spacialMethod(); 
     } 
     } 
    } 

    public void spacialMethod() { 
     System.out.println("Child special method called"); 
    } 
} 

public class Child2 extends Parent{ 
    public Child() { 
     super(); 
     this.accessor = null; 
    } 
}