以下内容不会编译,但我希望创建一些类似的功能,可以编译:
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 WillFitInMiniFoodFreezer extends Edible, SmallerThanABeachball, Freezeable{}
class MiniFoodFreezer extends StorageChest<WillFitInMiniFoodFreezer>{
}
...但是,如果Edible,SmallerThanABeachball和Freezeable都来自第三方库,而其他第三方库引用这些类型,其中一些具有必要的接口实现符合WillFitInMiniFoodFreezer的标准但未明确实现WillFitInMiniFoodFreezer?
答案 0 :(得分:3)
这里的问题是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
的任何东西,所以你失去了继承的任何直接好处。但是,您可以根据需要公开相同对象的不同类型视图。例如,假设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
}
答案 1 :(得分:0)
我担心你必须把它作为运行时检查,或者创建一个 包装IceCream并实现的适配器类 WillFitInMiniFoodFreezer。
这将解决您的问题,直到java解决其通用废话
您认为以下内容属于某些第三方库
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) {
}
}
//third party class that has function require type implementing the three interfaces
class SomeClass{
<T extends Edible & SmallerThanABeachball & Freezeable> void doSomething(T someThing){
System.out.println(someThing);
}
}
你想创建自己的存储,接受实现三个接口的类型Edible,SmallerThanABeachball,Freezeable
好的不是美丽而是一个简单的工作
创建实现此接口的接口
并创建一个除了扩展目标类和实现新的组合接口
之外什么都不做的类 interface WillFitInMiniFoodFreezer extends Edible, SmallerThanABeachball, Freezeable {
}
class MiniFoodFreezer extends StorageChest<WillFitInMiniFoodFreezer> {
}
//create your one version of iceCream implement the combining interface
class MyIceCream extends IceCream implements WillFitInMiniFoodFreezer {
}
//you can make new types implementing WillFitInMiniFoodFreezer
class Potato implements WillFitInMiniFoodFreezer {
}
class FreezerTest {
public FreezerTest() {
MiniFoodFreezer freezer = new MiniFoodFreezer();
//what you have wished
freezer.add(new Cat());//DESIRE COMPILE ERROR
freezer.add(new MyIceCream());//DESIRE OK
freezer.add(new Potato());//DESIRE OK
freezer.add(new MyBrother());///DESIRE COMPILE ERROR
freezer.add(new Banana());//DESIRE COMPILER ERROR
freezer.add(new Marbles());//DESIRE COMPILER ERROR
//third party function parametrized with the three interfaces
SomeClass thirdPartyClass = new SomeClass();
thirdPartyClass.doSomething(new MyIceCream()); // ^_^ ok
thirdPartyClass.doSomething(new Potato()); // ^_^ ok
thirdPartyClass.doSomething(new Cat());//:( not ok
}
}//end