2013-08-20 16 views
11

Voglio forzare la sottoclasse per implementare un metodo implementato di mia classe madre. Io guardo questo Java - Force implementation of an implemented method ma non riesco a convertire mia classe madre in una classe astratta.Come imporre l'implementazione di un metodo in sottoclasse senza utilizzare l'abstract?

public class myMotherClass { 

    myMethod { 

     ...some code .. 

    } 

} 

public class myClass extends myMotherClass { 

    myMethod { 

     ... other code ... 
    } 

} 

Quindi, in questo esempio, voglio forzare myClass a implementare myMethod.

Ci dispiace per il mio inglese ...

+1

In breve: non puoi senza renderlo astratto –

+0

@stonedsquirrel Che dire di un'interfaccia? –

+0

Questo non è possibile usando le annotazioni o lanciando un'eccezione se la classe non implementa il metodo? – Maniz

risposta

16

Non si può forzare una sottoclasse per eseguire l'override un metodo. Puoi solo forzarlo a implementare un metodo rendendolo astratto.

Quindi, se non si può fare myMotherClass astratto si può solo introdurre un altro superclasse che si estende myMotherClass e delega al metodo che deve essere implementata:

public abstract class EnforceImplementation extends myMotherClass { 

     public final void myMethod(){ 
      implementMyMethod(); 
     } 

     public abstract void implementMyMethod(); 
} 

EDIT

ho trovato un altro modo interessting di risolvere il problema nell'API hemcrest ad es usato da mockito.

public interface Matcher<T> extends SelfDescribing { 

    /** 
    * Evaluates the matcher for argument <var>item</var>. 
    * <p/> 
    * This method matches against Object, instead of the generic type T. This is 
    * because the caller of the Matcher does not know at runtime what the type is 
    * (because of type erasure with Java generics). It is down to the implementations 
    * to check the correct type. 
    * 
    * @param item the object against which the matcher is evaluated. 
    * @return <code>true</code> if <var>item</var> matches, otherwise <code>false</code>. 
    * 
    * @see BaseMatcher 
    */ 
    boolean matches(Object item); 

    /** 
    * This method simply acts a friendly reminder not to implement Matcher directly and 
    * instead extend BaseMatcher. It's easy to ignore JavaDoc, but a bit harder to ignore 
    * compile errors . 
    * 
    * @see Matcher for reasons why. 
    * @see BaseMatcher 
    */ 
    void _dont_implement_Matcher___instead_extend_BaseMatcher_(); 
} 

L'interfaccia specifica un metodo _dont_implement_Matcher___instead_extend_BaseMatcher_. Ovviamente non impedisce ad altri di implementare l'interfaccia Matcher, ma guida lo sviluppatore nella giusta direzione.

E la classe BaseMatcher implementa il metodo _dont_implement_Matcher___instead_extend_BaseMatcher_ come definitiva

public final void _dont_implement_Matcher___instead_extend_BaseMatcher_() { 
    // See Matcher interface for an explanation of this method. 
} 

Infine penso che questo sia un problema di progettazione, perché il BaseMatcher implementa obviouosly logica che ogni Matcher dovrebbe implementare. Quindi sarebbe stato meglio rendere la Matcher una classe astratta e utilizzare un metodo di modello.

Ma credo che l'abbiano fatto perché era il miglior compromesso tra compatibilità con il codice byte e nuove funzionalità.

4

Si potrebbe rielaborare la gerarchia in modo che le classi concrete sono solo foglie dell'albero.

Invece di

myClass extends myMotherClass 

consideri

myClass extends myMotherAbstractClass 
myMotherClass extends myMotherAbstractClass 

In questo modo la classe astratta viene ereditata da entrambe le classi istanziati. È probabile che in questo caso lo myMotherClass sia estremamente sottile, solo l'implementazione di myMethod.

-1

Se si desidera forzare l'implementazione del metodo, utilizzare interface.

public interface MyInterface{ 

    void myMethod(); 
} 

Ora, se qualcuno vuole implementare da questa interfaccia come MyClass implements MyInterface, è necessario implementare myMethod();

public MyClass implements MyInterface{ 

    public void myMethod{ 
    // do something 
    } 

} 
+2

Non penso che questo risolva il problema. – Lokesh

0

Una cosa maggior parte delle persone si affacciano è la seguente implementazione (anche se ho visto menzione di esso in un commento):

public class MyMotherClass { 

    public void myMethod() { 
     throw new RuntimeException("Method not overwritten"); 
    }  

} 

Nella maggior parte dei casi questo dovrebbe essere sufficiente, come si dovrebbe avere una qualche forma di test di accettazione (anche se sta solo testando la classe ereditaria a mano). In teoria, stai ancora introducendo la possibilità che nessuno si renderà conto che il metodo non è stato sovrascritto fino alla produzione.