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

时间:2012-09-02 02:15:25

标签: java generics interface

我想创建一个接口,强制实现它的每个类都具有某个功能,用于实现的类的类型。

所以说我有类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中正确地做到这一点?

4 个答案:

答案 0 :(得分:11)

您可以使用泛型:

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

public class MyClassA implements MyClass<MyClassA> 

这称为CRTP


这并不完美;它仍然允许像

这样的东西
public class MyClassB implements MyClass<MyClassA> 

要正确执行此操作,您需要更高级的类型 [citation needed] ,Java不支持。

答案 1 :(得分:1)

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

interface MyClass {
    MyClass doSomething();
}

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

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

答案 2 :(得分:1)

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

我希望能帮到你。

答案 3 :(得分:1)

您可能需要的是除了界面之外的父类。

我发现界面理想地用于定义行为,因此GroupElementA GroupElement声音在概念上更准确而不是GroupElementA 表现得像 GroupElement

我会考虑使用父类来实现你想要的东西。

/**
 * 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;
    }
}