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

} 

Когда я создаю экземпляр Child1, я хочу, чтобы автоматически был создан «равный», который также имеет тип Child1 и хранится в одноранговом. Аналогично для Child2, с одноранговым типом Child2.Вызов конструктора подкласса из абстрактного класса в Java

Проблема заключается в присвоении одноранговой собственности в родительском классе. Я не могу создать новый класс Child, вызвав new Child1(), потому что тогда он не будет работать для Child2. Как я могу это сделать? Есть ли ключевое слово, которое я могу использовать, чтобы ссылаться на дочерний класс? Что-то вроде new self()?

+1

Кажется, это странный образец для меня. Можете ли вы лучше использовать «ParentFactory» для создания экземпляров этих объектов? –

+0

Это очень странный дизайн. Возможно, кто-то из сверстников был бы исходным объектом? – Thilo

+0

Что будет с _peer_? Я имею в виду, какое использование оно служит, или какое-либо практическое вдохновение для этого. – soufrk

ответ

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

Похоже, что код может быть более простым.

+1

Но он хочет, чтобы «сверстник» был новым объектом, а не «этим» –

+0

... новым объектом, чей сверстник в свою очередь является «этим». – 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()) 
    } 
} 

Вот простейший способ, о котором я могу думать. Возможно, вы могли бы сделать это в родительском классе, используя хотя бы некоторый API-интерфейс отображения java (так что спросите «эту» ссылку, какой класс он представляет, и постройте новый класс этого типа. Возможно, он не работает в зависимости от того, как работают java-конструкторы. в C++, то «это» указатель на конструктор того же типа, что и класс конструкторов)

+0

Да.Это то, чего я надеялся избежать, но мне, возможно, придется это сделать. Cheers – Joel

+9

Не являются ли конструкторы Child1() и Child2() бесконечными? – banjollity

+0

Так они ... oops – workmad3

0

Что-то вроде этого:

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

Это один работает с конструктором по умолчанию, есть немного больше обмана, если принимать вы хотите создать новый одноранговый узел с конструктором, отличным от стандартного. См. Раздел «javadoc для класса».

Edit: исправлено зацикливание :)

+0

Прохладный. Это похоже на хорошее решение. Интересно, применит ли здесь вопрос Тило, или почему вы использовали внутренние классы? – Joel

+0

Разве это также не создает бесконечную рекурсию в конструкторах? Class.newInstance() по-прежнему вызывает конструктор. – Thilo

+0

, а не «boolean needPeer = false» (no peer), я полагаю, что сверстник должен быть оригинальным объектом ... OP должен переосмыслить свой дизайн. – Thilo

8

я не уверен, если это возможно, чтобы сделать это, не прибегая к циклам. Я убежден, что было бы намного проще писать это с использованием заводских методов вместо конструкторов.

+0

Да, определенно не следует использовать конструкторы напрямую. – egaga

+0

... Но не является ли метод фабрики обходным шаблоном для того, чтобы это было невозможно на языке? – xtofl

0

Обратите внимание, что без аксессора в родительском классе вы не можете получить одноранговый объект (вы не можете создать экземпляр Parent), поэтому этот дизайн имеет смысл только как доказательство концепции.

1

Начну с того, что я думаю, что это, наверное, очень плохой дизайн. И имена классов тоже плохие, но я буду придерживаться их.

Однако, один из способов борьбы с ним:

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

Я бы предложил заменить всю эту вещь с рисунком завода, где у вас есть полный контроль над тем, что получает добавил пэр, и вы не должны сделайте это в конструкторе.

-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

Ответ для ответа Leonid Kuskov

Ваш пример 2 всегда будет бросать StackOverflowException. Я искал код немного ниже, это правильная реализация для этого. Хотя спасибо вам дать мне указатели в этом направлении.

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