我试图创建一个实例化的通用类“ MultipleBoundsClass”,该类具有多个界限-一个名为“ OrderedPair”的类和一个名为“ Pair”的接口(有序对实现)。

香港专业教育学院试图删除接口边界,让我编译。但是我不知道为什么这样做,以及如何在包含接口边界的情况下成功实现它。

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类型不在其自身范围内?

最佳答案

我想提供一个示例,说明您可能如何使用多个范围。这很怪异,但可能有助于理解。

假设我们有一个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类:CardboardBoxGiftBoxMetalBarrelWoodBarrel,并根据其属性实现接口:

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

10-07 16:07