[英]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.