java突变体设计模式和编译器错误'Interface'不能用不同的类型参数'TypeA'和'TypeB'继承

时间:2015-09-18 23:45:58

标签: java android

我正在思考这个问题:我想要做的是[希望不要重新发明轮子]并且带来了[Android] Java事件机制,它允许子类预先定义一组任意“功能”使用getter和setter来激活单个回调。

我认为我在这里融合了Command,Visitor,Decorator,Facade和Observer模式的一些组合,并且在此过程中让自己感到困惑。 我已经编程超过20年了,但我觉得这个相当简单的问题是一个n00b! :(

我搜索了SO的编译器错误并阅读了许多结果,但我仍然没有找到适合我的解决方案。 (How to make a Java class that implements one interface with two generic types?似乎是我找到的最相关的一个,但我也希望在设置时一般性地获取值和触发事件回调。)

首先,让以下大部分有效的代码说明一切......

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();
    }
}

我没有兴趣试图弄清楚如何制作我想要编译的内容,而且我更感兴趣的是我对模式的滥用是基础的,所以我可以重写它是既简单又编译。

1 个答案:

答案 0 :(得分:0)

你正在滥用OOP的基本“模式” - 继承。谚语是“赞成作文而不是继承”。用“包含”来思考,而不是“是-a”。

以动物园为例。动物园只是一群动物,对吧?很自然地,我们可能希望将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

来操作设备的功能A.