Classe Java per imporre l'implementazione dei metodi pubblici di super classi

5

Ho il seguente:

public Class A {

    public void methodA() {
        ....
    }

    public void methodB() {
        ....
    }

}

Non ho il controllo sulla Classe A. Vorrei creare sottoclassi di Classe A con una restrizione che deve sovrascrivere metodoA () (la chiamata super.methodA () deve eseguire l'implementazione di Classe A). È possibile? è così, come?

    
posta 500865 01.08.2013 - 17:28
fonte

4 risposte

6

La prima cosa da capire qui è che questa parte dei requisiti: super.methodA() significa che si applica al codice delle classi che estendono A , in un modo definito in JLS 15.12.4.4-2. Invocazione del metodo usando super

An overridden instance method of a superclass may be accessed by using the keyword super to access the members of the immediate superclass, bypassing any overriding declaration in the class that contains the method invocation...

Diciamo che vogliamo un modo per creare sottoclassi specifiche di A tali che ogni volta che viene invocato super.methodA() in questi, è garantito che invece del codice che era in classe A (fuori dal nostro controllo) sarà esegui un altro codice, definito in alcune sottoclassi di A (sotto il nostro controllo).

Vediamo quali "strumenti" sono a nostra disposizione per ottenere quanto sopra.

  1. È necessario creare sottoclassi alcune, specifiche di A per richiamare alla mente il modo tradizionale di specializzarsi - sottoclassi, cioè considereremo la sottoclasse di A (chiamiamola B ) che ridefinisce (sostituisce) methodA nel modo in cui vogliamo.

  2. È necessario forzare una sottoclasse a fornire un codice che possa essere eseguito dove lo vogliamo nella superclasse può essere soddisfatto definendo un metodo astratto, chiamiamolo forcedImplementationInSubclass()

Ora abbiamo tutto ciò di cui abbiamo bisogno.

  • Definiremo una classe B che estende A , in modo che tutte le sottoclassi di B siano anche sottoclassi di A .
  • In B , sostituiremo methodA , quindi la sua implementazione in classe A non sarà più disponibile per sottoclassi di B .
  • Nel metodo sovrascritto in B invocheremo il metodo astratto forcedImplementationInSubclass() che garantirà che le sottoclassi di B dovranno definire il codice che alla fine verrà eseguito in methodA .

Di conseguenza, qualsiasi sottoclasse di B non sarà in grado di richiamare l'implementazione di methodA fornita nella classe A e invece, sarà garantito l'esecuzione del codice definito in alcune sottoclassi di B .

Estendere B è il modo per creare sottoclassi specifiche di A che si comportano come vogliamo. Il codice potrebbe apparire come segue:

public abstract class B extends A {
    // override, so that subclasses of B won't be able to get to super.methodA
    @Override public void methodA() {
        // invoke abstract method here (subclass would have to implement it)
        forcedImplementationInSubclass();
    }

    // define abstract method so that subclass would have to implement it
    protected abstract void forcedImplementationInSubclass();
}

// extending B is the way to get what we need
public class C extends B {
    // enforced implementation of the abstract method
    @Override protected void forcedImplementationInSubclass() {
        // that will be invoked when B.methodA() is called, and since B is-a A...
        System.out.print("Hello from implemented methodA");
    }

    public void testSuperMethodA() {
        // that will invoke B.methodA() which won't go to class A
        super.methodA();
    }

    public static void main(String[] args) {
        A a = new C();
        a.methodA(); // goes to B.methodA(), which in turn invokes C.forcedImplementationInSubclass()
        C c = new C();
        c.testSuperMethodA(); // won't go to class A
    }
}
    
risposta data 01.08.2013 - 20:52
fonte
4

Una volta che a un metodo è stata data un'implementazione, non c'è modo di renderla astratta di nuovo. Quindi, no, senza cambiare A non c'è modo di scrivere una classe B extends A in modo che tutte le sottoclassi di B debbano fornire un'altra implementazione, almeno non tramite il sistema di tipi.

Il meglio che puoi fare è scrivere un metodo in B che genera un'eccezione in fase di esecuzione. Questo costringe qualsiasi sottoclasse a sovrascrivere il metodo per essere utile, ma continuerà a compilare senza farlo.

    
risposta data 01.08.2013 - 17:38
fonte
-1

Penso che tu stia parlando di "classe astratta". Se si desidera che la sottoclasse di Classe A esegua l'override del metodoA () della Classe A, è necessario dichiarare il metodoA () come metodo astratto e la Classe A è una classe astratta.

Se qualche metodo di classe ha qualche implementazione allora agirà come implementazione predefinita delle sottoclassi. Le sottoclassi possono opzionalmente sovrascrivere quelle con la loro stessa implementazione. Se vuoi dare l'implementazione solo alla sottoclasse e forzare le sottoclassi a seguire un contratto (firma del metodo), allora questa è una chiara situazione di classe astratta.

class A
{
    void abstract methodA(); // No implementation.
}

class B extends A
{
    void methodA()
    {
        // Subclass implementation.
    }
}
    
risposta data 01.08.2013 - 17:35
fonte
-1

Prima di utilizzare reflection API, pensa al costo di esso.

È semplicemente facile da fare. Ad esempio:

C sottoclasse di B e B sottoclasse di A . Tutti e tre hanno un metodo methodName() per esempio.

public abstract class A {

    public void methodName() {
        System.out.println("Class A");
    }

}

public class B extends A {

    public void methodName() {
        super.methodName();
        System.out.println("Class B");
    }

    // Will call the super methodName
    public void hackSuper() {
        super.methodName();
    }

}

public class C extends B {

    public static void main(String[] args) {
        A a = new C();
        a.methodName();
    }

    @Override
    public void methodName() {
        /*super.methodName();*/
        hackSuper();
        System.out.println("Class C");
    }

}

Esegui la classe C L'output sarà:

Class A 
Class C

Invece dell'output:

Class A 
Class B 
Class C
    
risposta data 16.02.2015 - 13:14
fonte

Leggi altre domande sui tag