在java中使用接口中的实现类型

在java中使用接口中的实现类型,java,generics,interface,Java,Generics,Interface,我想为实现的类的类型创建一个接口,强制实现它的每个类都具有特定的功能 假设我有MyClassA、MyClassB、MyClassC等类,它们都需要自己类型的函数: 在MyClassA中: public class MyClassA implements MyClass { MyClassA function(MyClassA x) { doSomethingImplementedInMyClassA(x); } } 在MyClassB中: public clas

我想为实现的类的类型创建一个接口,强制实现它的每个类都具有特定的功能

假设我有MyClassA、MyClassB、MyClassC等类,它们都需要自己类型的函数:

在MyClassA中:

public class MyClassA implements MyClass {
    MyClassA function(MyClassA x) {
        doSomethingImplementedInMyClassA(x);
    }
}
在MyClassB中:

public class MyClassB implements MyClass {
    MyClassB function(MyClassB x) {
        doSomethingImplementedInMyClassB(x);
    }
}
问题是,如何编写接口
MyClass
来要求这样的功能

public interface MyClass {
    MyClass function(MyClass x);
}
显然不起作用,因为返回的类型是MyClass,而不是它的实现。如何在Java中正确执行此操作?

您可以使用泛型:

public interface MyClass<V extends MyClass<V>> {
    V function(V x);
}

public class MyClassA implements MyClass<MyClassA> 
公共接口MyClass{
V函数(vx);
}
公共类MyClassA实现MyClass
这就是所谓的


这并不完美;它仍然允许这样的事情发生

public class MyClassB implements MyClass<MyClassA> 
公共类MyClassB实现MyClass

要正确地执行此操作,您需要更高类型的[引文需要],Java不支持这种类型。

如果实现总是对参数调用方法,为什么不将该方法添加到接口中

interface MyClass {
    MyClass doSomething();
}

class MyClassA implements MyClass {
    MyClassA doSomething() {
        //implementation here
    }
}

class MyClassB implements MyClass {
    MyClassB doSomething() {
        //implementation here
    }
}

在Java中执行所需操作的正确方法如下:

首先,定义包含抽象方法的接口,该方法尚未定义。 请注意,接口不是类

public interface Animal {
    public Animal reproduceWith(Animal someAnimal);
}
然后定义实现接口的类并重写抽象方法,但现在使用您选择的代码实现它。这样,类中唯一相同的就是方法名。 这有效地迫使类实现某种方法

public class Dog implements Animal {

    @Override
    public Animal reproduceWith(Animal someAnimal) {
        return new Dog();
    }
}


public class Cat implements Animal {

    @Override
    public Animal reproduceWith(Animal someAnimal) {
        return new Cat();
    }
}
之后,您可以创建MyInterface的列表,并调用相同的方法对其进行迭代,即使它是不同的类

List<Animal> list = new ArrayList<Animal>();
list.add(new Cat());
list.add(new Dog());

Animal cat = new Cat();
Animal dog = new Dog();

for (Animal animal : list) {
    System.out.println(animal.reproduceWith(cat));
    System.out.println(animal.reproduceWith(dog));
}
List List=new ArrayList();
添加(新的Cat());
添加(新狗());
动物猫=新猫();
动物狗=新狗();
用于(动物:列表){
系统输出打印LN(动物繁殖(cat));
系统输出打印(带狗的动物繁殖);
}

我希望这对您有所帮助。

您可能需要的是一个接口之外的父类

我发现界面是定义行为的理想方式,因此
GroupElementA
是一个
GroupElement
听起来在概念上比
GroupElementA
更准确

<>我会考虑使用一个父类来实现你想要的。

/**
 * An abstract group element.
 */
abstract class GroupElement
{
    // attributes of all group elements
}

/**
 * Defines behavior for objects that can be multiplied with
 * GroupElements.
 */
interface GroupElementMultipliable
{
    public GroupElement multiplyBy(GroupElement groupElement);
}

/**
 * Defines behavior for objects that can be divided by
 * GroupElements.
 */
interface GroupElementDivisible
{
    public GroupElement divideBy(GroupElement groupElement);
}

/**
 * An abstract GroupElement that can perform operations like
 * multiplication and division.
 *
 * Then again this class may not be necessary. The interfaces
 * implemented here may actually be directly implemented by
 * GroupElementA. GroupElementA will also be the one to inherit
 * GroupElement.
 */
abstract class OperableGroupElement extends GroupElement
        implements GroupElementMultipliable, GroupElementDivisible
{
    // attributes of all operable group elements
}

/**
 * A concrete GroupElement that can perform operations like
 * multiplication and division.
 */
class GroupElementA extends OperableGroupElement
{
    @Override
    public GroupElementA multiplyBy(GroupElement groupElement)
    {
        // Since we expect to multiply with another GroupElementA
        // we attempt to typcast the groupElement
        GroupElementA groupElementA = (GroupElementA) groupElement;

        // do multiplication operation -- this * groupElementA
        // then return new self
        return this;
    }

    @Override
    public GroupElementA divideBy(GroupElement groupElement)
    {
        // Since we expect to divide by another GroupElementA
        // we attempt to typcast the groupElement
        GroupElementA groupElementA = (GroupElementA) groupElement;

        // do division operation -- this / groupElementA
        // then return new self
        return this;
    }
}

啊哈,使用类作为自己的泛型,这很聪明!谢谢@USE1111929:BTW,你的意思是“作为它自己的通用参数”。这是一个C++习语,所以它与问题完全无关,java有这个功能。检查我的答案。有什么原因不能将
doSomethingImplementedInMyClass()
添加到接口中吗?我不确定这会有什么帮助?通过创建一个“强制实现它的每个类都具有特定功能的接口,对于实现的类“类型”,您想实现什么?你是如何试图解决这个问题可能是不可能的,但替代方案应该存在;以及类似的方法。因此,我将创建一个接口
GroupElement
,并要求
GroupElement
的每个实现都将乘法例程定义为
GroupElement multiplyBy(GroupElement b的实现){…}
。。。我应该怎样做才能获得
a.剂量(b)的效果在您的代码中?公共MyInterface myAbstractMethod();在接口和类中实现它。我将编辑答案。我仍然不知道这是怎么做的
a.doSomething(b)。您的代码中的
a
b
是什么?a是MyClassA,b是MyClassB。因此,您可以调用接口的方法并将接口作为参数提供给它,但类可以不同。诀窍在于,您知道方法是相同的,因此可以调用它,而无需检查类型。我编辑了我的答案,让它更清楚。不客气,但这也给了你同样的可能性;)在本例中,基本上您的泛型类型是接口本身。MyInterface a=新的MyClassA();MyInterface b=新的MyClassB();a、 剂量测定法(b);这是一个有趣的方法。然而,如果需要类型转换,那么它仍然比SLaks建议的通用参数方法快?它当然不会产生更短的代码。你的方法到底有什么好处?我倾向于尽可能地使用接口,因为它们不会导致继承速度减慢(甚至抽象类也会这样做,iirc)。实际上,这也是我第一次了解CRTP(多亏SLaks),所以我无法真正比较我的方法。是的,它确实占用了更多的LOC,但这是一个很好的OO解决方案。我不是一个真正的表演迷,但我也读过关于表演的书,唯一主要的问题似乎是打字。