2009-05-21 15 views
5
public abstract class Parent { 

    private Parent peer; 

    public Parent() { 
     peer = new ??????("to call overloaded constructor"); 
    } 

    public Parent(String someString) { 
    } 

} 

public class Child1 extends parent { 

} 

public class Child2 extends parent { 

} 

Quando costruisco un'istanza di Child1, voglio che venga creato automaticamente un "peer" che sia anche di tipo Child1 e che sia archiviato nella proprietà peer. Allo stesso modo per Child2, con un peer di tipo Child2.Chiamare il costruttore della sottoclasse dalla classe astratta in Java

Il problema è, sull'assegnazione della proprietà peer nella classe padre. Non riesco a costruire una nuova classe figlio chiamando new Child1() perché non funzionerebbe per Child2. Come posso fare questo? C'è una parola chiave che posso usare che farebbe riferimento alla classe bambino? Qualcosa come new self()?

+1

Sembra uno strano schema per me. Potrebbe essere meglio usare "ParentFactory" per istanziare questi oggetti? –

+0

Questo è un design molto strano. Il pari del pari sarebbe l'oggetto originale, suppongo? – Thilo

+0

Cosa diventa della _peer_? Intendo quale uso serve o qualsiasi ispirazione pratica per questo. – soufrk

risposta

2
public abstract class Parent implements Clonable{ 

    private Object peer; 

    // Example 1 
    public Parent() { 
    try { 
     peer = this.clone(); 
    } catch (CloneNotSupportedException e) { 
     e.printStackTrace(); 
    } 
    } 

    // Example 2 
    public Parent(String name) { 
    try { 
     peer = this.getClass().getConstructor(String.class).newInstance(name); 
    } catch (Exception e) { 
     e.printStackTrace(); 
    } 
    } 
    } 

    public <T extends Parent> T getPeer() { 
    return (T)peer; 
    } 
} 

public class Child01 extends Parent { } 

public class Child02 extends Parent { } 

Sembra che il codice possa essere più semplice.

+1

Ma vuole che "peer" sia un nuovo oggetto, non "questo" –

+0

... un nuovo oggetto, il cui peer a sua volta è "questo". – Thilo

-3
public abstract class Parent { 

    private Parent peer; 

    public Parent(Parent peer) { 
     this.peer = peer; 
    } 

    public Parent(String someString) { 
    } 

} 

public class Child1 extends parent { 
    public Child1() { 
     super(new Child1()) 
    } 
} 

public class Child2 extends parent { 
    public Child2() { 
     super(new Child2()) 
    } 
} 

Ecco il modo più semplice che riesco a pensare. Probabilmente potresti farlo nella classe genitore usando alcune delle API di java reflection (quindi chiedi al riferimento "this" quale classe è e costruisci una nuova classe di quel tipo.) Potrebbe non funzionare a seconda di come funzionano i costruttori java. in C++, il puntatore 'this' in un costruttore è dello stesso tipo della classe di costruttori)

+0

Sì.Questo è quello che speravo di evitare, ma potrei averlo dovuto andare. Cheers – Joel

+9

I costruttori Child1() e Child2() non si chiamano infinitamente? – banjollity

+0

Quindi sono ... oops – workmad3

0

Qualcosa di simile a questo:

public class Peer { 
    public static abstract class Parent { 
      private Parent peer; 

      protected Parent(boolean needPeer) { 
        if (needPeer) { 
          try { 
            peer = getClass().newInstance(); 
          } 
          catch (Throwable e) { 
            System.err.println(e); 
          } 
        } 
      } 

      public String getPeerClass() { 
        return peer.getClass().toString(); 
      } 
    } 

    public static class Child1 extends Parent { 
      public Child1() { 
        this(false); 
      } 
      public Child1(boolean needPeer) { 
        super(needPeer); 
      } 
    } 

    public static class Child2 extends Parent { 
      public Child2() { 
        this(false); 
      } 
      public Child2(boolean needPeer) { 
        super(needPeer); 
      } 
    } 

    public static void main(String[] args) { 
      Parent p1 = new Child1(true); 
      Parent p2 = new Child2(true); 

      System.out.println(p1.getPeerClass()); 
      System.out.println(p2.getPeerClass()); 
    } 
} 

questo funziona con il costruttore di default, c'è un po 'più di inganno coinvolti se vuoi costruire un nuovo peer con un costruttore non predefinito. Vedi The javadoc for Class.

Edit: fissa la ricorsione infinita :)

+0

Cool. Questa sembra una soluzione ok. Mi chiedo se il problema sollevato da Thilo si applicherebbe qui, o è per questo che hai usato le classi interne? – Joel

+0

Questo non crea anche una ricorsione infinita nei costruttori? Class.newInstance() chiama ancora il costruttore. – Thilo

+0

piuttosto che "booleano needPeer = false" (no peer), suppongo che il peer peer debba essere l'oggetto originale ... L'OP dovrebbe ripensare il suo design. – Thilo

8

non sono sicuro se è possibile farlo senza incorrere in cicli. Sono convinto che sarebbe molto più chiaro scrivere questo usando metodi di fabbrica invece di costruttori.

+0

Sì, sicuramente non dovresti usare direttamente i costruttori. – egaga

+0

... Ma non è un metodo factory un pattern di workaround per questo non è possibile nella lingua, davvero? – xtofl

0

Si noti che senza un accessorio nella classe padre non è possibile ottenere l'oggetto peer (non è possibile creare un'istanza Parent), quindi questo progetto ha senso solo come prova di concetto.

1

Inizierò col dire che penso che sia probabilmente un design davvero pessimo. E anche i nomi delle classi sono cattivi, ma io li seguirò.

Tuttavia, un modo di trattare con esso:

public abstract class Parent { 
    interface PeerFactory { 
     Parent create(Parent peer); 
    } 
    private final Parent peer; 

    protected Parent(Parent peer) { 
     super(); 
     this.peer = peer; 
    } 
    protected Parent(PeerFactory peerFactory) { 
     super(); 
     this.peer = peerFactory.create(this); 
    } 
} 

public class Child1 extends parent { 
    private static final PeerFactory peerFactory = new PeerFactory { 
     public Parent create(Parent peer) { 
      return new Child1(peer); 
     } 
    }; 
    public Child1() { 
     super(peerFactory); 
    } 
    private Child1(Peer peer) { 
     super(peer); 
    } 
} 
0

Vorrei suggerire di sostituire tutta questa faccenda con un modello di fabbrica, dove si ha il controllo completo su ciò che viene aggiunto un pari e non si deve fallo nel costruttore.

-1
public abstract class Parent implements Clonable { 
    private Object peer; 

    // Example 1 
    public Parent() { 
    try { 
     peer = this.clone(); 
    } catch (CloneNotSupportedException e) { 
     e.printStackTrace(); 
    } 
    } 

    // Example 2 
    public Parent(String name) { 
    try { 
     peer = this.getClass().getConstructor(String.class).newInstance(name); 
    } catch (Exception e) { 
     e.printStackTrace(); 
    } 
    } 

} 

public <T extends Parent> T getPeer() { 
return (T)peer; 
} 

public class Child01 extends Parent { } 

public class Child02 extends Parent { } 
0

Rispondendo per risposta di Leonid Kuskov

Il vostro esempio 2 sarà sempre buttare uno StackOverflowException. Ho trafficato con il codice un po 'sotto e l'implementazione corretta per quello. Comunque grazie a te per darmi dei consigli in quella direzione.

public class AbstractClassDemo { 

    public static void main(String[] args) { 
     Child1 c1 = new Child1(); 
     System.out.println(c1.getPeer().getClass().getName()); 
    } 

} 

abstract class Parent { 
    private Object peer; 

    public Parent() { 

    } 

    public Parent(String s) { 
     try { 
      setPeer(this.getClass().getConstructor(String.class) 
        .newInstance("")); 
     } catch (Exception e) { 
      e.printStackTrace(); 
     } 
    } 

    public Object getPeer() { 
     return peer; 
    } 

    public void setPeer(Object peer) { 
     this.peer = peer; 
    } 
} 

class Child1 extends Parent implements Cloneable { 
    public Child1() { 
     super("Child1"); 
    } 

    public Child1(String child1) { 
    } 
} 

class Child2 extends Parent implements Cloneable { 
    public Child2() { 
     super("Child2"); 
    } 

    public Child2(String child2) { 
    } 
} 
Problemi correlati