java 如何为几个类型特定的类定义一个通用接口?

ar7v8xwq  于 2022-12-17  发布在  Java
关注(0)|答案(2)|浏览(138)

当我尝试编写接口程序时,我经常发现自己处于以下情况:

  • 我有几个非常相似的类,表示不同类型的容器或算法。
  • 我想为这些类定义一个公共接口。

例如,考虑一个字符串容器,这样的容器很可能有字符串处理方法,因为这些方法很容易用泛型接口表示,所以我忽略它们,这里我想把重点放在可以用来处理或提供对其他字符串容器的引用的方法上:

public class StringContainer {
    StringContainer produce() {
        return new StringContainer();
    }

    void consume(StringContainer stringContainer) {
    }
}

此类可以很好地用于以下代码:

public class Main {
    public static void main(String[] args) {
        StringContainer stringContainer = new StringContainer();
        stringContainer.produce();
        stringContainer.consume(stringContainer);
    }
}

问题是:我使用了一个具体的类而不是一个接口来引用字符串容器。如果我想在后面引入一个双容器或列表容器,并且想让代码的其余部分保持原样,该怎么办?
也许泛型可以形成这个问题的解决方案?下面是我的尝试。我首先定义一个泛型容器类:

interface Container<T> {
    Container<T> produce();

    void consume(Container<T> container);
}

然后,我创建以下形式的特定于类型的实现:

public class StringContainer implements Container<String> {
    @Override
    public Container<String> produce() {
        return new StringContainer();
    }

    @Override
    public void consume(Container<String> container) {
    }

    public void consume(StringContainer container) {
    }
}

上述类可按如下方式使用:

public class Main {
    public static void main(String[] args) {
        Container<String> stringContainer = new StringContainer();
        stringContainer.produce();
        stringContainer.consume(stringContainer);
    }
}

然而,上述方法具有几个缺点:

  1. consume(Container<String> container)方法接受StringContainer以外的其他类型。
    1.在consume(Container<String> container)中,当处理container时必须使用参数化类型Container<String>,我不能将其赋给StringContainer变量(没有类型检查或强制转换)。
    1.替代的consume(StringContainer container)方法是为StringContainer对象定义的,但不能从Container<String>引用调用。
    1.最后,对我来说,Container<String> stringContainer = new StringContainer();行有一个看起来很笨拙的符号,它表明new StringContainer()中缺少一个菱形操作符。
    为几个类型特定的类定义通用接口的惯用方法是什么,它没有(所有)上述缺点?
    我是否应该忽略第4点,通过添加类型检查/强制转换来处理第1点和第2点,在传递的对象不是StringContainer的情况下抛出UnsupportedOperationExceptionIllegalArgumentException?或者有其他使用泛型的方法吗?例如,类型界限能帮助我吗?或者我是否应该寻找泛型之外的解决方案?
unhi4e5o

unhi4e5o1#

这就是你要找的吗?这叫做递归类型绑定。

interface Container<T extends Container<T>> {
    T produce();

    void consume(T container);
}

class StringContainer implements Container<StringContainer> {
    @Override
    public StringContainer produce() {
        return new StringContainer();
    }
    
    @Override
    public void consume(StringContainer container) {
    }
}
qacovj5a

qacovj5a2#

看起来你有两个API,你应该用单独的接口分别对待它们。是的,你可以用不同的方法名将它们合并到同一个接口中。
我认为你应该有两个接口分别用于你的“容器”和“容器的容器”。下面是我的想法:

interface Container<T> {
    T produce();
    void consume(T container);
}

interface MetaContainer<T, R extends Container<T>> {
    R produceContainer();
    void consumeContainer(R container);
}

class StringContainer implements Container<String>, MetaContainer<String, StringContainer> {
    @Override
    public String produce() {
        return "";
    }

    @Override
    public void consume(String container) {
    }

    @Override
    public StringContainer produceContainer() {
        return this;
    }

    @Override
    public void consumeContainer(StringContainer container) {
    }
}

我使用同一个类实现了这两个接口,以模拟StringContainer类。

相关问题