【问题标题】:Java generics with typed container/containment relationships between two classes具有两个类之间的类型化容器/包含关系的 Java 泛型
【发布时间】:2011-03-09 13:59:24
【问题描述】:

我希望生成一些包含以下内容的基类

class Container<T extends Containee>
{
     T containee;
     public T getContents(){return containee;}
     public void setContents(T contents){ containee = contents; containee.setContainer(this); }
}

class Containee<T extends Container>
{
     T container;
     public T getContainer(){return container;}
     public void setContainer(T container){this.container = container;}
}

这里有一个循环定义问题,我认为我可以使用通配符来缓解

class Container<T extends Containee<?>>
class Containee<T extends Container<?>>

除了编译器抱怨containee.setContainer(this)。我已经破解了一些可以编译超类的临时解决方案,但没有任何东西可以用于子类,例如

class Foo extends Container<Bar>
class Bar extends Containee<Foo> 

泛型教程和常见问题解答似乎没有与此相关的任何明显内容。如何使用泛型表达这种关系?

谢谢

【问题讨论】:

标签: java generics data-structures


【解决方案1】:

可能是这样的:

abstract class Container<
    THIS extends Container<THIS, T>,
    T extends Containee<T, THIS>
> {
    T containee;

    protected abstract THIS getThis();

    public T getContents() {
        return containee;
    }
    public void setContents(T contents){
        containee = contents;
        containee.setContainer(getThis());
    }
}

class Containee<
    THIS extends Containee<THIS, T>,
    T extends Container<T, THIS>
> {
    T container;
    public T getContainer() {
        return container;
    }
    public void setContainer(T container) {
        this.container = container;
    }
}

(或者可能是泛型较少的东西。)

【讨论】:

  • 泛型最复杂的用法之一 .. :) 我同意你在这个问题上使用较少泛型的观点。
  • 我想我更喜欢选角!不过有趣的技巧,谢谢。
【解决方案2】:

试试这个:

class Container<T extends Containee<Container<T>>>
{
   T containee;
   public T getContents(){return containee;}
   public void setContents(T contents){ containee = contents; containee.setContainer(this); }
}

class Containee<T extends Container<? extends Containee<T>>>
{
   T container;
   public T getContainer(){return container;}
   public void setContainer(T container){this.container = container;}
}

class Bar extends Containee<Container<Bar>> {  
}

class Foo extends Container<Bar> {
}

Foo 现在是一个接受 Bar 对象的容器,而 Bar 可以添加到任何扩展 Container 的容器中,所以这也是可能的:

class Baz extends Container<Bar> {
}

Baz 也是 Bar 对象的容器。

【讨论】:

  • 这很好,但不是我需要的。例如,在 Bar 的方法中,我希望能够在不强制转换的情况下编写 Foo f = this.getContainer()。这个想法是容器为容器提供 API,反之亦然,两者都是子类特定的。还是谢谢。
【解决方案3】:

使用普通的旧多态会更好吗?

class Container
{
    Containee containee;
    public Containee getContents(){return containee;}
    public void setContents(Containee contents){ containee = contents; containee.setContainer(this); }
}

class Containee
{
    Container container;
    public Container getContainer(){return container;}
    public void setContainer(Container container){this.container = container;}
}

【讨论】:

  • 这取决于。多态性并没有捕捉到 Containee 需要特定类型的容器。例如,如果我有class Fish extends Containee {} class Aquarium extends Container{} class Desert extends Container {},您的解决方案允许我在沙漠中放置一条鱼而不是水族馆。在 Tom 的解决方案中,编译器会阻止这种情况。 (当然,除非是未经检查的演员表)
【解决方案4】:

您的第一个解决方案有什么问题?

class Container<T extends Containee>
class Containee<T extends Container>

【讨论】:

    猜你喜欢
    • 1970-01-01
    • 1970-01-01
    • 1970-01-01
    • 1970-01-01
    • 1970-01-01
    • 2015-10-24
    • 1970-01-01
    • 2019-07-14
    • 1970-01-01
    相关资源
    最近更新 更多