java - 扩展泛型类时如何传递多个泛型参数

标签 java generics

以下内容不会编译,但我希望创建一些可以编译的类似功能:

public class FreezerTest
{
interface Edible{}
interface SmallerThanABeachball{}
interface Freezeable{}
abstract class BoxedItem
    {}
class Marbles extends BoxedItem
    {}
class IceCream extends BoxedItem implements Freezeable, SmallerThanABeachball, Edible
    {}
class MyBrother
    {}
class Banana implements Edible, SmallerThanABeachball
    {}
class Cat implements SmallerThanABeachball
    {}

abstract class StorageChest<T>{
    public void add(T toStore){}
    }

class MiniFoodFreezer extends StoreageChest<Freezeable & Edible & SmallerThanABeachball>{
    }

public FreezerTest(){
    MiniFoodFreezer freezer = new MiniFoodFreezer();
    freezer.add(new Cat());//DESIRE COMPILE ERROR
    freezer.add(new IceCream());//DESIRE OK
    freezer.add(new MyBrother());///DESIRE COMPILE ERROR
    freezer.add(new Banana());//DESIRE COMPILER ERROR
    freezer.add(new Marbles());//DESIRE COMPILER ERROR
    }
}//end 

一个想法是创建一个包罗万象的接口(interface),然后传递它:

interface WillFitInMiniFoodFreezer extends Edible, SmallerThanABeachball, Freezeable{}
class MiniFoodFreezer extends StorageChest<WillFitInMiniFoodFreezer>{
}

...但是,如果 Edible、SmallerThanABeachball 和 Freezeable 都来自第 3 方库,并且其他第三方库引用这些类型,其中一些具有满足 WillFitInMiniFoodFreezer 标准但没有明确要求的接口(interface)实现,该怎么办实现 WillFitInMiniFoodFreezer?

最佳答案

这里的问题是 Freezeable & Edible & SmallerThanABeachball本身不是类型 - 符号 ( & ) 只能在声明类型参数时用于定义多个上限,例如 <T extends Freezeable & Edible & SmallerThanABeachball> .此语言限制在此处进一步讨论:How to reference a generic return type with multiple bounds

一种解决方法是结合使用组合和通用 add方法:

class Freezer extends StoreageChest<Freezeable> { }

class MiniFoodFreezer {

    private final Freezer freezer = new Freezer();

    public <T extends Freezeable & Edible & SmallerThanABeachball> void add(
            final T toStore
    ) {
        freezer.add(toStore);
    }
}

缺点是 MiniFoodFreezer不再 StoreageChest任何东西,所以你失去了继承的任何直接好处。但是,您可以根据需要公开相同对象的不同类型的 View 。例如,假设 StoreageChest<T>工具 Iterable<T> :

class MiniFoodFreezer {

    private final Freezer freezer = new Freezer();

    public <T extends Freezeable & Edible & SmallerThanABeachball> void add(
            final T toStore
    ) {
        freezer.add(toStore);
    }

    public Iterable<Freezeable> asFreezables() {
        return freezer;
    }

    public Iterable<Edible> asEdibles() {
        // this is okay because add must take an Edible and Iterable is read-only
        @SuppressWarnings("unchecked")
        final Iterable<Edible> edibles = (Iterable<Edible>)(Iterable<?>)freezer;
        return edibles;
    }

    public Iterable<SmallerThanABeachball> asSmallerThanBeachballs() {
        // same reasoning as above
        @SuppressWarnings("unchecked")
        final Iterable<SmallerThanABeachball> smallerThanBeachballs =
                (Iterable<SmallerThanABeachball>)(Iterable<?>)freezer;
        return smallerThanBeachballs;
    }
}

然后我们可以做:

final MiniFoodFreezer miniFoodFreezer = new MiniFoodFreezer();
miniFoodFreezer.add(new IceCream());
miniFoodFreezer.add(new SnoCone());
miniFoodFreezer.add(new Slushy());

for (final Freezeable freezable : miniFoodFreezer.asFreezables()) {
    // do freezable stuff
}

for (final Edible edible : miniFoodFreezer.asEdibles()) {
    // do edible stuff
}

for (
        final SmallerThanABeachball smallerThanABeachBall :
        miniFoodFreezer.asSmallerThanBeachballs()
) {
    // do smaller-than-a-beach-ball stuff
}

关于java - 扩展泛型类时如何传递多个泛型参数,我们在Stack Overflow上找到一个类似的问题: https://stackoverflow.com/questions/20716651/

相关文章:

java - fork 一个进程

c - 未定义引用 : Generic vector in C with Macro

c# - 如何获取泛型类型参数的类型名称?

c# - 具有通用类型约束的工厂模式

java - 为什么 Java 在 While 循环中跳过我的 If 语句?

java - 初始化抽象类的一般变体

java - hibernate/JPA : only one entry can have specific field value

java - 当我创建 Eclipse 项目时,是否为每个项目再次复制了 Java/Android 依赖项?

typescript :获取实例的通用类型

c# - 通用 Linq 查询 NotSupportedException : Could not parse expression