Java Generics:接收实现类的类型参数的接口方法

zer*_*gen 22 java generics types

在Java中,是否可以定义一个接口,该接口具有接收实现类参数的方法?

接口:

public interface MyInterface {
   public <T is/extends of the type of the implementing class> void method(T object);
}
Run Code Online (Sandbox Code Playgroud)

类:

public class A implements MyInterface {

    public void method(A object) {
       ...
    }

}
Run Code Online (Sandbox Code Playgroud)

我想要避免的是一个类可以用另一个类来实现MyInterface.

所以这不应该被允许:

public class A implements MyInterface<B> {

    public void method(B object) {
       ...
    }

}    
Run Code Online (Sandbox Code Playgroud)





编辑:

好吧,我试着以另一种方式描述我想要实现的目标.我希望有几个类具有接受该类类型的arg的方法.所以除了上面的A类之外,让我们说另一个看起来像这样的B类:

public class B implements MyInterface {

    public void method(B object) {
       ...
    }

}
Run Code Online (Sandbox Code Playgroud)

展位类A和B的共同点是一种称为"方法"的方法,它接收类本身类型的arg.

在我的项目中,我希望实现以下目标.我正在写一个小游戏,并希望实现某种碰撞检测.基本上我想通过做一些"智能"多态调用来做到这一点.

我定义了一个接口ICollisionReceiver,如下所示:

public interface ICollisionReceiver<T extends IShape> extends IShape {

    public boolean collides(T t);

}
Run Code Online (Sandbox Code Playgroud)

我定义了另一个这样的界面:

public interface ICollisionChecker<T extends ICollisionChecker<T>> extends IShape {

    public void addCollisionReceiver(ICollisionReceiver<T> receiver);

    public void removeCollisionReceiver(ICollisionReceiver<T> receiver);

}
Run Code Online (Sandbox Code Playgroud)

现在,例如我的播放器实现接口ICollisionReceiver,因为播放器接收冲突并处理它们.这应该以通用的方式完成,所以例如我有盒子和圆圈,现在玩家实现ICollisionReceiver <Box>和ICollisionReceiver <Circle>所以我有两种方法

@Override
public boolean collides(final Box b) {        
    ...
    return false;
}
Run Code Online (Sandbox Code Playgroud)

@Override
public boolean collides(final Circle c) {        
    ...
    return false;
}
Run Code Online (Sandbox Code Playgroud)

在我的box和circle类中,我可以注册ICollisionReceivers,然后在update方法中执行以下操作:

    boolean conti = true;
    int i=0;
    while(conti && i<collisionReceivers.size()) {
        final ICollisionReceiver<Bonus> rec = collisionReceivers.get(i);               
        if(this.collidesWith(rec)) {
            conti = rec.collides(this);
        }            
        ++i;
    }
Run Code Online (Sandbox Code Playgroud)

这基本上检查此框是否与某个接收器冲突,然后调用接收器collides()方法.

现在重点是,我想确保两个类框和圆圈仅使用自己的类型实现ICollisionChecker接口.

我明确可以通过做这样的事情来做到这一点

public class Bonus extends AnimatedSprite implements ICollisionChecker<Bonus>...
Run Code Online (Sandbox Code Playgroud)

但这对我来说并不是很令人满意......

对不起,很长的帖子,我希望这说清楚.

new*_*cct 30

你想要什么是不可能的Java,并没有用.

所以这不应该被允许:

为什么不?这有什么用途?泛型不适合您进行任意限制.泛型只对消除你需要的演员阵容很有用,因为它可以证明演员阵容总是安全的.

只要public class A implements MyInterface<B>是类型安全的,没有必要制定禁止它的任意限制.

您只需将界面定义为

public interface MyInterface<T> {
   public void method(T object);
}
Run Code Online (Sandbox Code Playgroud)

你可以定义你的课程

public class A implements MyInterface<A> {
    public void method(A object) {
    }
}
Run Code Online (Sandbox Code Playgroud)

如果有人定义了一个类

public class B implements MyInterface<A> {
    public void method(A object) {
    }
}
Run Code Online (Sandbox Code Playgroud)

那就这样吧.你为什么在乎?它会引起什么问题?

  • 哈,我知道在第一句话之后就是你.总是试图在城外运行CRTP :) (2认同)

Esk*_*sko 5

好吧,这至少是可能的:

public interface SelfImplementer<T extends SelfImplementer<T>> {
    void method(T self);
}
Run Code Online (Sandbox Code Playgroud)

如您所见,Generic声明看起来有点像无限递归,而且我很确定,如果Java 没有类型擦除,那么将是-幸运的是(?)所有Generics实际上是Objects在编译器处理完之后的,所以您可以做到这一点

public class Impl implements SelfImplementer<Impl> {
    @Override
    public void method(Impl self) {
        System.out.println("Hello!");
    }
}
Run Code Online (Sandbox Code Playgroud)

和预期的一样

public static void main(String[] args) {
    Impl impl = new Impl();
    impl.method(impl);
}
Run Code Online (Sandbox Code Playgroud)

打印出来

Hello!
Run Code Online (Sandbox Code Playgroud)

  • 作为一个脚注,我发现这完全是荒谬的,我不会鼓励任何人实际使用它。 (3认同)