簡體   English   中英

java突變設計模式和編譯器錯誤“接口”不能用不同的類型參數“ TypeA”和“ TypeB”繼承

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

 
粵ICP備18138465號  © 2020-2024 STACKOOM.COM