我想创建一个接口,强制实现它的每个类都具有某个功能,用于实现的类的类型。
所以说我有类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中正确地做到这一点?
答案 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;
}
}