从Java中的抽象类调用子类构造函数

时间:2009-05-21 07:58:37

标签: java

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的实例时,我想要一个自动构造的“peer”,它也是Child1类型,并存储在peer属性中。同样对于Child2,具有Child2类型的对等。

问题在于,在父类中分配对等属性。我无法通过调用new Child1()来构造一个新的Child类,因为它对Child2不起作用。我怎样才能做到这一点?我可以使用哪个关键字来引用子类?像new self()

这样的东西

9 个答案:

答案 0 :(得分:8)

我不确定是否可以在不进入循环的情况下执行此操作。我相信使用工厂方法而不是构造函数来编写它会更清楚。

答案 1 :(得分: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 { }

似乎代码可能更简单。

答案 2 :(得分: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);
    }   
}

答案 3 :(得分:0)

请注意,如果父类中没有访问器,则无法获取对等对象(您无法实例化Parent),因此此设计仅作为概念证明才有意义。

答案 4 :(得分: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) {
    }
}

答案 5 :(得分:0)

我建议用Factory模式替换整个事件,在那里你可以完全控制添加对象的内容,而不必在构造函数中执行。

答案 6 :(得分: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。

编辑:修复无限递归:)

答案 7 :(得分:-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 { }

答案 8 :(得分:-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())
    }
}

这是我能想到的最简单的方法。您可以使用一些java反射API在父类中执行此操作(因此请询问'this'引用它是什么类并构造该类型的新类。它可能无法工作,具体取决于java构造函数的工作方式。在C ++中,构造函数中的“this”指针与构造函数类的类型相同