2009-05-21 5 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 { 

} 

Cuando construyo una instancia de Niño1, quiero un "par" para ser construido de forma automática, que también es de tipo Niño1, y se almacena en la propiedad de pares. Del mismo modo para Child2, con un par de tipo Child2.llamada constructor de la subclase de la clase abstracta en Java

El problema es, en la asignación de la propiedad del par en la clase principal. No puedo construir una nueva clase Child llamando al new Child1() porque entonces no funcionaría para Child2. ¿Cómo puedo hacer esto? ¿Hay alguna palabra clave que pueda usar que se refiera a la clase secundaria? Algo así como new self()?

+1

Me parece un patrón extraño. ¿Sería mejor utilizar una "ParentFactory" para crear instancias de estos objetos? –

+0

Ese es un diseño muy extraño. El par del par sería el objeto original, supongo. – Thilo

+0

¿Qué pasa con el _peer_? Me refiero a qué uso sirve, o cualquier inspiración práctica para esto. – soufrk

Respuesta

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 { } 

Parece que el código puede ser más simple.

+1

Pero él quiere que "peer" sea un objeto nuevo, no "esto" –

+0

... un nuevo objeto, cuyo par a su vez es "esto". – 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()) 
    } 
} 

Aquí está la manera más simple que se me ocurre. Sin embargo, probablemente puedas hacerlo en la clase para padres utilizando algunas de las API java reflection (así que pregunta a la referencia 'this' qué clase es y crea una nueva clase de ese tipo. Puede que no funcione según cómo funcionen los constructores de java. en C++, el puntero 'this' en un constructor es del mismo tipo que la clase constructores)

+0

Sí.Eso es lo que esperaba evitar, pero podría tener que irme así. Cheers – Joel

+9

¿Los constructores Child1() y Child2() no se llaman infinitamente? – banjollity

+0

Así que están ... oops – workmad3

0

Algo como esto:

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()); 
    } 
} 

ésta trabaja con el constructor por defecto, hay un poco más el engaño implica su desea construir un nuevo par con un constructor no predeterminado. Ver el javadoc para Class.

Editar: fija la recursividad infinita :)

+0

Cool. Esto parece una buena solución. Me pregunto si el problema planteado por Thilo se aplicaría aquí, ¿o es por eso que has usado las clases internas? – Joel

+0

¿No crea esto también una recursión infinita en los constructores? Class.newInstance() todavía llama al constructor. – Thilo

+0

en lugar de "boolean needPeer = false" (sin igual), supongo que el par del par debe ser el objeto original ... El OP debería reconsiderar su diseño. – Thilo

8

No estoy seguro de si es posible hacer esto sin caer en ciclos. Estoy convencido de que sería mucho más claro escribir esto utilizando métodos de fábrica en lugar de constructores.

+0

Sí, definitivamente no debería usar constructores directamente. – egaga

+0

... ¿Pero no es un método de fábrica un patrón de solución para que esto no sea posible en el idioma, realmente? – xtofl

0

Tenga en cuenta que sin un descriptor de acceso en la clase principal no puede obtener el objeto par (no se puede crear una instancia del elemento principal), por lo que este diseño solo tiene sentido como prueba de concepto.

1

Comenzaré diciendo que creo que probablemente sea un diseño realmente malo. Y los nombres de clase también son malos, pero me quedaré con ellos.

Sin embargo, una manera de tratar con ella:

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

que sugeriría la sustitución de todo esto con un patrón de fábrica, donde se tiene un control completo sobre lo que obtiene un compañero añadió y que no tiene que hazlo en el constructor

-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

En respuesta a la respuesta de Leonid Kuskov

Su ejemplo 2 siempre lanzar una StackOverflowException. Jugueteé con el código un poco más abajo es la implementación correcta para eso. Aunque gracias a usted para darme consejos en esa dirección.

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) { 
    } 
} 
Cuestiones relacionadas