简体   繁体   English

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

[英]use implementation type in interface in java

I want to make an interface that forces each class that implements it to have a certain functionality, for the implemented class' type. 我想创建一个接口,强制实现它的每个类具有某个功能,用于实现的类的类型。

So say I have classes MyClassA, MyClassB, MyClassC, etc. that all need a function on their own type: 所以说我有类MyClassA,MyClassB,MyClassC等都需要一个自己类型的函数:

in MyClassA: 在MyClassA中:

public class MyClassA implements MyClass {
    MyClassA function(MyClassA x) {
        doSomethingImplementedInMyClassA(x);
    }
}

in MyClassB: 在MyClassB中:

public class MyClassB implements MyClass {
    MyClassB function(MyClassB x) {
        doSomethingImplementedInMyClassB(x);
    }
}

The question is, how to write the interface MyClass to require such function? 问题是,如何编写接口MyClass来要求这样的功能?

public interface MyClass {
    MyClass function(MyClass x);
}

obviously doesn't work, since the returning type is MyClass and not its implementation. 显然不起作用,因为返回类型是MyClass而不是它的实现。 How to do this properly in Java? 如何在Java中正确地做到这一点?

You can use generics: 你可以使用泛型:

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

public class MyClassA implements MyClass<MyClassA> 

This is called the CRTP . 这称为CRTP


This is not perfect; 这并不完美; it would still allow things like 它仍然会允许这样的事情

public class MyClassB implements MyClass<MyClassA> 

To do this correctly, you need higher-kinded types [citation needed] , which Java does not support. 要正确执行此操作,您需要更高级的类型[需要引证] ,Java不支持。

If the implementation always calls a method on the argument, why not just add that method to the interface? 如果实现总是在参数上调用方法,为什么不直接将该方法添加到接口?

interface MyClass {
    MyClass doSomething();
}

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

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

The proper way to do what you want to do in Java is like this: 在Java中执行您想要执行的操作的正确方法是这样的:

1st you define your interface containing a abstract method , that is a method that is not defined yet. 首先,您定义包含抽象方法的接口,这是一种尚未定义的方法。 Remind that an interface is not a class! 提醒一个界面不是一个类!

public interface Animal {
    public Animal reproduceWith(Animal someAnimal);
}

Then you define the classes that implements the interface and you override the abstract method but now you implement it with the code of your choice. 然后定义实现接口的类,并覆盖抽象方法,但现在使用您选择的代码实现它。 That way the only thing that is the same in the class is the method name. 这样,类中唯一相同的是方法名称。 This effectively forces a class to implement a certain method. 这有效地迫使类实现某种方法。

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

After that you could for example make a list of MyInterface and iterate over it calling the same method even if its a different class. 之后你可以创建一个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));
}

I hope that helps you out. 我希望能帮到你。

What you probably need is a parent class apart from an interface. 您可能需要的是除了接口之外的父类。

I find an interface is ideally used to define behavior thus GroupElementA is a GroupElement sounds conceptually more accurate rather than GroupElementA behaves like a GroupElement . 我发现接口理想地用于定义行为,因此GroupElementA 是一个 GroupElement声音在概念上更准确,而GroupElementA 行为就像 GroupElement

I would consider using a parent class to achieve what you want to have. 我会考虑使用父类来实现你想要的东西。

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

声明:本站的技术帖子网页,遵循CC BY-SA 4.0协议,如果您需要转载,请注明本站网址或者原文地址。任何问题请咨询:yoyou2525@163.com.

 
粤ICP备18138465号  © 2020-2024 STACKOOM.COM