【问题标题】:How to use multiple bounds correctly?如何正确使用多个边界?
【发布时间】:2019-02-01 07:14:16
【问题描述】:

我正在尝试创建一个实例化一个名为“MultipleBoundsClass”的通用类,该类具有多个边界 - 一个名为“OrderedPair”的类和一个名为“Pair”的接口(Ordered Pair 实现)。

我试过删除接口边界,让我编译。但我不知道为什么会这样,以及 Id 是如何在包含接口边界的情况下成功实现的。

public interface Pair<K, V>
{
  public K getKey();
  public V getValue();
}

public class OrderedPair<K, V> implements Pair
{
  private K key;
  private V value;
  public OrderedPair(K key, V value)
  {
    this.key = key;
    this.value = value;
  }
  public K getKey()
  {
    return key;
  }
  public V getValue()
  {
    return value;
  }
}

class OrderedPair {}
interface Pair {}
public class MultipleBounds<T extends OrderedPair & Pair>
{
  private T t;
  public MultipleBounds(T t)
  {
    this.t = t;
  }
  public T getPair()
  {
    return t;
  }
}

public static void main(String[] args)
{
  OrderedPair<String, Integer> p1 = new OrderedPair<>("even", 8);
  MultipleBounds<OrderedPair> myPair = new MultipleBounds<OrderedPair>(p1);
}

我收到错误“类型参数 OrderedPair 不在类型变量 T 的范围内”。有界类型将泛型参数的参数限制为您定义的类及其子类,那么当接口被包含为当前边界时,为什么类型 OrderedPair 不在其自身范围内?

【问题讨论】:

  • 请在代码中指定错误出现的位置。我猜它在你的主要方法中
  • 您可能不需要同时扩展OrderedPairPair。使用public class MultipleBounds&lt;T extends Pair&gt;,因为OrderedPair 已经实现了Pair 并且允许在MultipleBounds 中成为T 类型
  • @coffman21 的作用与仅扩展类一样。所以你说的是扩展两者时错误的原因,是 OrderedPair 已经实现了 Pair 吗?那么,多重边界的唯一有效场景是当参数的类型是扩展类的子类时?
  • @Dylan 抱歉,这个问题没有任何意义。为什么你又在MultipleBounds 之前声明class OrderedPair {}interface Pair {},没有类型?在这里,您的 OrderedBound 类并没有真正实现 Pair,因此不能用作 T 类型 - 它不在范围内,因为不实现 Pair
  • @Dylan 你没听懂。你有:public interface Pair&lt;K, V&gt; { /* blah blah */ },然后你又有:interface Pair {},相同的文件,重复的界面,相同的类。那不行。它是否代表您的代码库?如果是这样,您可能需要删除重复项。

标签: java bounded-types multiple-bounds


【解决方案1】:

我想提供一个示例,说明如何使用多个边界。这很奇怪,但可能有助于理解事情。

假设我们有一个Container,我们可以put 里面有东西。

abstract class Container {
    private Object content;

    public void put(Object object) { this.content = object; }
    public Object get() { return content; }
}

然后,有一些接口可以为这些容器定义一些属性。他们可能是Rollable 和/或Inflammable

interface Rollable { void roll(); /* rolls somehow */ }
interface Inflammable { void burnItself(); /* burns somehow */ }

然后,我们定义具体的Container类:一个CardboardBox、一个GiftBox、一个MetalBarrel和一个WoodBarrel,并根据它们的属性实现接口:

class CardboardBox extends Container implements Inflammable {
    @Override
    public void burnItself() { /* omit implementation */ }
}

class GiftBox extends Container implements Rollable, Inflammable {
    @Override
    public void burnItself() { /* omit implementation */ }
    @Override
    public void roll() { /* omit implementation */ }
}

class MetalBarrel extends Container implements Rollable {
    @Override
    public void roll() { /* omit implementation */ }
}

class WoodBarrel extends Container implements Rollable, Inflammable {
    @Override
    public void burnItself() { /* omit implementation */ }
    @Override
    public void roll() { /* omit implementation */ }
}

现在,真正的奇怪。假设您要创建一个Stock,其中所有的东西都必须是Rollable。和Inflammable。因为你想把你所有的容器都卷进去,并且能够烧掉其中一个。你定义一个Stock

class Stock <T extends Container & Rollable & Inflammable> {
    private List<T> containers;

    void addContainer(T container) { containers.add(container); }

    void rollAllContainers() { containers.forEach(Rollable::roll); }

    void burnContainer(int index) { containers.get(index).burnItself(); }
}

然后您就可以创建其中之一。你没有绑定Container 类型;只是它的属性——因为它们是由接口定义的。

public static void main(String[] args) {
    Stock<GiftBox> giftBoxStock = new Stock<>();

    GiftBox giftBox = new GiftBox();
    giftBox.put("a gift");
    GiftBox giftBox1 = new GiftBox();
    giftBox1.put("another gift");

    giftBoxStock.addContainer(giftBox);
    giftBoxStock.addContainer(giftBox1);
    giftBoxStock.rollAllContainers();
    giftBoxStock.burnContainer(0);

    Stock<WoodBarrel> woodBarrelStock = new Stock<>();

    WoodBarrel woodBarrel = new WoodBarrel();
    woodBarrel.put("wine");
    WoodBarrel woodBarrel1 = new WoodBarrel();
    woodBarrel1.put("gas");

    woodBarrelStock.addContainer(woodBarrel);
    woodBarrelStock.addContainer(woodBarrel1);
    woodBarrelStock.rollAllContainers();
    woodBarrelStock.burnContainer(1);
}

【讨论】:

    猜你喜欢
    • 2023-03-16
    • 2012-02-10
    • 1970-01-01
    • 1970-01-01
    • 1970-01-01
    • 1970-01-01
    • 1970-01-01
    • 2010-12-01
    • 1970-01-01
    相关资源
    最近更新 更多