繁体   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