[英]Java generic multiple bounds error:cannot be inherited with different type arguments
[英]java mutant design pattern and compiler error 'Interface' cannot be inherited with different type arguments 'TypeA' and 'TypeB'
我对此不以为然:我想做的是[希望不要重新发明轮子,并且]提出了一个[Android] Java事件机制,该机制允许子类使用getter和pres预先定义任意一组“功能”。触发单个回调的设置器。
我想我在这里融合了Command,Visitor,Decorator,Facade和Observer模式的某种组合,并在此过程中使自己感到困惑。 我已经进行了20多年的编程,但是在这个相当简单的问题上,我感觉像个n00b! :(
我已经在SO中搜索了编译器错误并阅读了许多结果,但是我仍然没有找到适合我的解决方案。 ( 如何制作一个实现具有两种泛型类型的接口的Java类?似乎是我找到的最相关的类,但是我也想泛化地获取值并在设置它们时将事件触发回调)。
首先,让以下大部分有效的代码说明一切...
interface IFeature
{
}
interface IFeatureCallbacks<T extends IFeature>
{
boolean onChanged(Feature<T> c);
}
public static class Feature<T extends IFeature>
{
private Set<IFeatureCallbacks<T>> listeners = new LinkedHashSet<>();
public void addListener(IFeatureCallbacks<T> listener)
{
listeners.add(listener);
}
public void removeListener(IFeatureCallbacks<T> listener)
{
listeners.remove(listener);
}
protected void onChanged()
{
for (IFeatureCallbacks<T> listener : listeners)
{
listener.onChanged(this);
}
}
}
//
interface IFeatureA
extends IFeature
{
int getA();
}
interface IFeatureACallbacks
extends IFeatureCallbacks<IFeatureA>
{
}
public static class FeatureA
extends Feature<IFeatureA>
implements IFeatureA
{
private int a;
public void setA(int value)
{
a = value;
onChanged();
}
@Override
public int getA()
{
return a;
}
}
//
interface IFeatureB
extends IFeature
{
boolean getB();
}
interface IFeatureBCallbacks
extends IFeatureCallbacks<IFeatureB>
{
}
public static class FeatureB
extends Feature<IFeatureB>
implements IFeatureB
{
private boolean b;
public void setB(boolean value)
{
b = value;
onChanged();
}
@Override
public boolean getB()
{
return b;
}
}
//
interface IDeviceWithFeatureA
extends IFeatureA
{
}
interface IDeviceWithFeatureACallbacks
extends IFeatureACallbacks
{
}
public static class DeviceWithFeatureA
extends Feature<IDeviceWithFeatureA>
implements IDeviceWithFeatureA
{
FeatureA a = new FeatureA();
public void addListener(IDeviceWithFeatureACallbacks listener)
{
a.addListener(listener);
}
public void setA(int value)
{
a.setA(value);
}
@Override
public int getA()
{
return a.getA();
}
}
//
interface IDeviceWithFeatureB
extends IFeatureB
{
}
interface IDeviceWithFeatureBCallbacks
extends IFeatureBCallbacks
{
}
public static class DeviceWithFeatureAB
extends Feature<IDeviceWithFeatureB>
implements IDeviceWithFeatureB
{
FeatureB b = new FeatureB();
public void addListener(IDeviceWithFeatureBCallbacks listener)
{
b.addListener(listener);
}
public void setB(boolean value)
{
b.setB(value);
}
@Override
public boolean getB()
{
return b.getB();
}
}
上面的代码似乎工作正常,尽管它闻起来有些不对劲。 问题是当我尝试执行此操作时:
interface IDeviceWithFeatureAAndFeatureB
extends IFeatureA, IFeatureB
{
}
/*
Compiler error:
'IFeatureCallbacks' cannot be inherited with different type arguments 'IFeatureA' and 'IFeatureB'
*/
interface IDeviceWithFeatureAAndFeatureBCallbacks
extends IFeatureACallbacks, IFeatureBCallbacks
{
}
public static class DeviceWithFeatureAB
extends Feature<IDeviceWithFeatureAAndFeatureB>
implements IDeviceWithFeatureAAndFeatureB
{
FeatureA a = new FeatureA();
FeatureB b = new FeatureB();
public void addListener(IDeviceWithFeatureAAndFeatureBCallbacks listener)
{
a.addListener(listener);
b.addListener(listener);
}
public void setA(int value)
{
a.setA(value);
}
@Override
public int getA()
{
return a.getA();
}
public void setB(boolean value)
{
b.setB(value);
}
@Override
public boolean getB()
{
return b.getB();
}
}
我对试图弄清楚如何使我要编译的内容不感兴趣,而对我滥用模式的想法则不太感兴趣,因此我可以将其重写为既简单又容易编译。
您正在滥用OOP的基本“模式”-继承。 格言是“偏爱组成胜于继承”。 用“包含”而不是“是”来思考。
以Zoo为例。 动物园只是一群动物,对不对? 因此,自然地,我们可能想将Zoo声明为Set<Animal>
子类型。 甚至没有class Zoo extends HashSet<Animal>
。
但是,这可能是错误的设计。 动物园实际上是很多东西。 当然,它包含一组动物。 但其中也包含一组人(作为工作人员,而不是展览品(尽管...))。 所以最好
class Zoo
Set<Animal> animals(){ ... }
Set<Person> workers(){ ... }
在需要将动物园视为一组动物的任何地方,只需使用zoo.animals()
; 将其视为类型转换或投影。 我们在这里不需要继承。
在您的设计中,您有太多的类型。 更糟糕的是,类型关系过多。 似乎您只需要一个通用类即可读取/写入T
值,并包含T
侦听器
class Feature<T>
T value;
// getter
// setter
Set<ChangeListener<T>> listeners;
interface ChangeListener<T>
void onChange(T oldValue, T newValue)
设备包含很多功能
class SomeDevice
Feature<Integer> featureA = new Feature<>();
Feature<Boolean> featureB = new Feature<>();
而已。 您可以通过在其上运行的设备的特征的操作featureA
。
声明:本站的技术帖子网页,遵循CC BY-SA 4.0协议,如果您需要转载,请注明本站网址或者原文地址。任何问题请咨询:yoyou2525@163.com.