Java 使用相互引用的最终成员对两个类进行子类化

Java 使用相互引用的最终成员对两个类进行子类化,java,subclass,Java,Subclass,假设我有两个这样的班 公共类Foo { 受保护的儿童; 公共食物( { child=新条(此条); } } 公共类酒吧 { 受保护的最终Foo父母; 公共酒吧(Foo家长) { this.parent=parent; } } 我想创建一个子类Foo,Foo2,它的子类是Bar2,它是Bar的子类。我可以这样做: 公共类Foo { 受保护的儿童; 公共食物( { child=新的makeChild(); } 受保护的条makeChild() { 返回新条(本条); } } 公共类Foo2扩展了F

假设我有两个这样的班

公共类Foo
{
受保护的儿童;
公共食物(
{
child=新条(此条);
}
}
公共类酒吧
{
受保护的最终Foo父母;
公共酒吧(Foo家长)
{
this.parent=parent;
}
}
我想创建一个子类
Foo
Foo2
,它的子类是
Bar2
,它是
Bar
的子类。我可以这样做:

公共类Foo
{
受保护的儿童;
公共食物(
{
child=新的makeChild();
}
受保护的条makeChild()
{
返回新条(本条);
}
}
公共类Foo2扩展了Foo
{
@凌驾
受保护的条makeChild()
{
返回新的Bar2(本);
}
}
然而。但像这样的事情是行不通的:

公共类Foo
{
受保护的儿童;
公共食物(
{
这个(新吧)(这个);;
}
受保护的Foo(Bar-child)
{
这个孩子=孩子;
}
}
因为在调用超类型构造函数之前,
newbar(this)
引用了
this

我认为有两种方法可以解决这个问题:

1) 我可以将成员设置为私有的和非最终的,然后创建setter,如果已经设置了,就会抛出一个异常,但这看起来很笨拙,而且只能在运行时检测到任何编码问题

2) 我让
Foo
构造函数将要使用的
Bar
类型的
Class
对象作为参数,然后使用反射调用该类的构造函数。然而,这似乎是我正在努力做的事情的重量级

有没有我遗漏的编码技术或设计模式

有没有我遗漏的编码技术或设计模式

我想到了这个模式。只需将参数全部从构造函数中取出,生成构成接口上方类的类型,然后在需要时注入适当的具体类型

Foo接口

interface Foo {
  public void setBar(Bar bar);
  public Bar getBar();
}
interface Bar {
  public void setFoo(Foo foo);
  public Foo getFoo();
}
条形接口

interface Foo {
  public void setBar(Bar bar);
  public Bar getBar();
}
interface Bar {
  public void setFoo(Foo foo);
  public Foo getFoo();
}

我一直在考虑使用或类似的方法进一步解耦并自动执行注入。

其中一个选择是为初始化创建单独的函数,并在子类ctor中调用init方法:

e、 g

当然,它假设Foo和Bar是耦合的,依赖Foo来实例化Bar是合理的。但是,在大多数情况下,您应该考虑通过DI框架向Foo注入条。


在评论中,您提到了最终报告的必要性

虽然在VAR成员现在是私有的情况下,我不认为这是一个大问题,但是这里有另一种方式(实际上类似于上面描述的),如果初始化工作和你的问题一样简单:
class Foo {
    protected final Bar child;

    public Foo() {
        this.child = new Bar(this);
    }
}

class Foo2 {
    public Foo2() {
        this.child = new Bar2(this);
    }
}

我还没有测试过代码,但我相信它应该可以工作:p

您的问题是关于循环引用的简单问题


首先,您应该设计类以避免循环引用,原因有很多

接下来,如果您没有选择,那么最好的解决方案是使用“依赖注入”。为什么?这样想:

  • 您必须创建Foo对象
  • 在创建foo时,还需要创建Bar
  • 但是,出于明显的原因,您不希望硬编码条形码实例
  • 由于您提到的原因,在构造函数中调用“可重写”方法是有问题的

  • 因此依赖注入可以安全地进行拯救。

    但是在这种情况下,
    子成员不能是
    final
    ,因为它不是在构造函数中设置的。哦,我还没有认识到“final”是您的要求之一。然而,鉴于变量现在是私有的,将其作为非最终变量似乎不是那么关键
    不起作用,因为它在调用超类型构造函数之前引用了
    this
    。很好,让我更新一下它(尽管我很好奇这有多有用:()这需要将成员设为非
    final
    ,然后在
    setXYZ()
    方法在单个对象上被多次调用。@MatthewCline关于final是正确的,但我认为没有必要出现异常,尤其是在自动注入的情况下。“首先,您应该设计类以避免循环引用,原因有很多。”.读了这篇链接文章,然后重新思考,我决定将这两个类合并为一个类。