扩展泛型类时如何传递多个泛型参数 [英] How to pass multiple generic parameters when extending a generic class

查看:100
本文介绍了扩展泛型类时如何传递多个泛型参数的处理方法,对大家解决问题具有一定的参考价值,需要的朋友们下面随着小编来一起学习吧!

问题描述

下面的代码不会编译,但我希望创建一些类似的功能来编译:

The following will not compile but I wish to create something of similar functionality which will compile:

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 

一个想法是创建一个全面的接口,然后通过

One thought was to create an all-encompassing interface and then pass that:

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

...但是如果Edible,SmallerThanABeachball和Freezeable都来自第三方库和其他第三方库引用这些类型,其中一些必须满足WillFitInMiniFoodFreezer条件的接口实现,但没有明确实现WillFitInMiniFoodFreezer?

...however what if Edible, SmallerThanABeachball, and Freezeable are all from a 3rd party library and other third-party libraries refer to these types, some of which have the interface implementations necessary meet the criteria for WillFitInMiniFoodFreezer but do not explicitly implement WillFitInMiniFoodFreezer?

推荐答案

这里的问题是 Freezeable&食用& SmallerThanABeachball 本身不是一种类型 - 例如,在声明类型参数时,&符号(& )只能用于定义多个上限,例如< T扩展了Freezeable&食用& SmallerThanABeachball> 。此语言限制在此处进一步讨论:如何引用具有多个边界的泛型返回类型

The issue here is that Freezeable & Edible & SmallerThanABeachball is not itself a type - the ampersand (&) can only be used to define multiple upper bounds when declaring a type parameter, for example <T extends Freezeable & Edible & SmallerThanABeachball>. This language limitation is further discussed here: How to reference a generic return type with multiple bounds

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

One workaround is to use a combination of composition and a generic add method:

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 ,所以您失去了继承的直接好处。但是,您可以根据需要公开不同类型的视图。例如,假设 StoreageChest< T> implements Iterable< T>

The downside being that MiniFoodFreezer no longer is-a StoreageChest of anything, so you lose any direct benefits of inheritance. However, you can expose differently typed views of the same objects as needed. For example, assume StoreageChest<T> implements 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
}

这篇关于扩展泛型类时如何传递多个泛型参数的文章就介绍到这了,希望我们推荐的答案对大家有所帮助,也希望大家多多支持IT屋!

查看全文
登录 关闭
扫码关注1秒登录
发送“验证码”获取 | 15天全站免登陆