我是一名 C++ 程序员,在 C++ 中我可以做这样的事情:

class SuperSuper
{
    virtual void newItem()=0;
}

class SubSuperA:public SuperSuper
{
     virtual void newItem()
     {
         //do something
     }
}

class SubSuperB:public SuperSuper
{
     virtual void newItem()
     {
         //do something different (disappear! :)
     }
}

template <class T>
class SubSub:public T
{
    virtual void newItem()
    {
         T::newItem();
         //do a third thing
    }
}

我想在 Java 中做到这一点,但是我觉得它(至少直接)是不可能的

我在 Java 中很容易地设置了前三个类,如下所示:
public abstract class SuperSuper
{
    abstract void newItem(Item item);
}

public class SubSuperA extends SuperSuper
{
    @Override void newItem(Item item)
    {
        //stuff
    }
}

public class SubSuperB extends SuperSuper
{
    @Override void newItem(Item item)
    {
        //other stuff
    }
}
//SubSuperC,D,etc

目前正在实现第四个,如下所示:
SubSuperA sa=new SubSuperA() {
    @Override public void newItem(Item item)
    {
        super.newItem(item);
        //A lot of stuff that will be changing constantly throughout development
    }
};

SubSuperB sb=new SubSuperB() {
    @Override public void newItem(Item item)
    {
        super.newItem(item);
        //A lot of stuff that will be changing constantly throughout development
    }
};

请注意,这两个覆盖具有相同的功能。无论它基于什么 SubSuper*,替换 newItem() 都是相同的。显然,这将是一场噩梦。我希望我可以像这样声明一个 SubSub 类
 public class SubSub<T> extends T {
    @Override public void newItem(Item item)
    {
        super.newItem(item);
        //A lot of stuff that will be changing constantly throughout development
    }
 }

我可以像这样实例化
 SubSub ss=new SubSub<SubSuperA>

等等......但是这个错误在java中:
"Cannot refer to the type parameter T as a supertype."

我根据该错误环顾四周,发现 Extend from Generic Supertype? 声称使用该方法无法实现我想要做的事情。

我真正需要做的是:我有一个平台不可知的 twitter 客户端,它只处理接收推文、存储它们等。它有一个抽象的 Column 类(SuperSuper),我可以为各种不同类型的列(SubSuper)(家庭时间线,提及等),并且每个都过滤掉他们想要在 newItem() 中显示的推文。我希望能够为不同平台插入各种 GUI,并且我需要客户端调用 GUI 特定函数 (SubSub) 来处理将每个单独的推文添加到 GUI 库。拥有可以扩展任何 Column 派生类的 GUI 特定类将是理想的解决方案

由于显然这种直接实现在 Java 中是不可能的,我想知道是否有一些语法技巧可以实现非常相似的东西,或者我是否应该创建一个接口(interface),该接口(interface)将由 SuperSuper 和 SuperSub* 存储和调用由我的 GUI 处理程序而不是 SubSub 实现。

最佳答案

模板可以使用 Java 的泛型。然而,在 Java 中,接口(interface)远比继承更受欢迎。这是因为 Java 不支持多重继承。

在 C++ 中,您可以扩展多个类。

class X : public A, public B, private C { }

因为 C++ 不区分虚拟和非虚拟类,只有虚拟成员和非虚拟成员,所以在可能有也可能没有虚拟方法的类之间没有正式的区别。

另一方面,Java 具有三种不同的类类型:
  • 具体(完全非虚拟,所有方法都是具体的)
  • 抽象(部分虚拟,部分非虚拟)
  • 接口(interface)(完全虚拟,没有具体方法)

  • 在 Java 中,虚拟方法被称为抽象方法,因此我将在此之后将它们称为抽象方法。

    Java 也有泛型。泛型在语法上类似于模板,但在实现方面完全不同。我会将实现研究留给您(在您的搜索中使用的关键字是“擦除”)。

    泛型在类上声明。例如,Java 与 C++ vector 的等价物是 ArrayList 类。它的用法非常相似:
    List<String> strs = new ArrayList<String>();
    

    这里, ListArrayList 的一种父类(super class)型。 List 是一个接口(interface),ArrayList 实现了它。 List 本身在其声明中声明了一个泛型类型,如下所示:
    public interface List<E> ... {
    
        // ...
    
        E get(int index);
    
        // ...
    }
    

    注意 get 如何返回 E 。这里,E 没有具体定义。它是一个泛型类型,在这种情况下,任何东西都可以在它的位置使用, StringObjectBoolean ,你自己的类等。
    ArrayList 实现了 List ,并且还声明了一个泛型类型:
    public ArrayList<E> implements List<E>, ... {
    
        // ...
    
        public E get(int index) {
            // bounds check
            return elements[i];
        }
    
        // ...
    }
    

    您还可以使用类型边界限制泛型的类型。这有点超出了本文的范围,因为您想要的并不是真正的泛型。你想要接口(interface)。

    在您的示例中,您将首先使用 newItem 声明一个接口(interface)。
    public interface A {
        void newItem();
    }
    

    每个方法都必须来自具体的实现或接口(interface),因此需要这个接口(interface)。具体来说,这个接口(interface)相当于 SuperSuper 。它是一个完全虚拟的类(接口(interface))。现在为您的类(class):
    public class B implements A {
        @Override
        public void newItem() {
            // Do something
        }
    }
    
    public class C implements A {
        @Override
        public void newItem() {
            // Do something else
        }
    }
    

    对于像我这样在 C++ 方面没有太多经验的人来说,最后一点有点令人困惑,但我假设您在说的是您想使用 newItem 方法创建模板类型。在 Java 中,这将是 A 接口(interface)的另一种实现,或者您可以扩展 B 或 C 并覆盖它们的方法。
    public class D extends B {
        @Override
        public void newItem() {
            // And yet another something else
        }
    }
    

    然后使用带有 newItem 方法的东西就像这样简单:
    A a = new B(); // or "new C()" or "new D()"
    a.newItem();
    

    就像你怎么说
    SuperSuper* a = new SubSuperA();
    

    在 Java 中,您可以对接口(interface)、抽象类和具体类执行相同的操作,就像我上面所做的那样。

    所以我认为接口(interface)是解决您问题的方法。我强烈建议阅读 Java 中如何使用接口(interface)。它们在没有多重继承的情况下提供了强大的类型。我会很快找到几个链接。
  • polymorphism 的复习。
  • 在线教科书,关于 Polymorphism and Interfaces 的章节。
  • 通用接口(interface)书籍: Interface Oriented Design

  • 希望那些帮助。如果您需要任何说明,请告诉我。

    10-07 13:05
    查看更多