Java Generics: метод интерфейса, который получает аргумент типа реализующего класса
В Java можно определить интерфейс, который имеет метод, который получает аргумент класса реализации?
интерфейс:
public interface MyInterface {
public <T is/extends of the type of the implementing class> void method(T object);
}
Класс:
public class A implements MyInterface {
public void method(A object) {
...
}
}
Я хочу избежать того, что класс может реализовать MyInterface с другим классом, таким как сам.
Поэтому это не должно быть разрешено:
public class A implements MyInterface<B> {
public void method(B object) {
...
}
}
Edit:
Хорошо, я пытаюсь описать по-другому то, чего хочу достичь. Я хочу иметь несколько классов, у которых есть метод, который принимает аргумент этого типа класса. Таким образом, дополнительно к классу A сверху можно сказать, что следующий класс B выглядит следующим образом:
public class B implements MyInterface {
public void method(B object) {
...
}
}
у каких классов кабин A и B есть общий метод - метод, который получает аргумент типа самого класса.
В моем проекте я хочу добиться следующего. Я пишу небольшую игру и хочу реализовать какое-то обнаружение столкновения. в основном я хочу это сделать, выполняя некоторые "умные" полиморфические вызовы.
Я определил интерфейс ICollisionReceiver, который выглядит так:
public interface ICollisionReceiver<T extends IShape> extends IShape {
public boolean collides(T t);
}
и я определил другой интерфейс:
public interface ICollisionChecker<T extends ICollisionChecker<T>> extends IShape {
public void addCollisionReceiver(ICollisionReceiver<T> receiver);
public void removeCollisionReceiver(ICollisionReceiver<T> receiver);
}
Теперь, например, мой плеер реализует интерфейс ICollisionReceiver, поскольку игрок получает столкновений и обрабатывает их. Это должно быть сделано в общем виде, поэтому, например, у меня есть поля и круг, теперь Player реализует ICollisionReceiver <Box> и ICollisionReceiver < Круг > поэтому у меня есть оба метода
@Override
public boolean collides(final Box b) {
...
return false;
}
и
@Override
public boolean collides(final Circle c) {
...
return false;
}
В моем классе box и circle я могу зарегистрировать ICollisionReceivers, а затем я делаю следующее в методе обновления:
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;
}
это в основном проверяет, сталкивается ли это поле с определенным приемником, а затем вызывает метод colliders() получателей.
Теперь дело в том, что я хочу убедиться, что оба класса и круг классов реализуют интерфейс ICollisionChecker только с их собственным типом.
Я явно могу сделать это, сделав что-то вроде этого
public class Bonus extends AnimatedSprite implements ICollisionChecker<Bonus>...
но для меня это не очень приятно...
Извините за длинный пост, надеюсь, это даёт понять.
Ответы
Ответ 1
То, что вы хотите, невозможно в Java, и не полезно.
Поэтому это не должно быть разрешено:
Почему бы и нет? Какая цель это служит? Дженерики - это не для вас произвольные ограничения. Дженерики полезны только для устранения бросков, которые вам в противном случае нужны, потому что это может доказать, что литье всегда безопасно.
Пока public class A implements MyInterface<B>
безопасен по типу, нет смысла делать произвольное ограничение, запрещающее его.
Вы должны просто определить свой интерфейс как
public interface MyInterface<T> {
public void method(T object);
}
и вы можете определить свой класс
public class A implements MyInterface<A> {
public void method(A object) {
}
}
а если кто-то определяет класс
public class B implements MyInterface<A> {
public void method(A object) {
}
}
то пусть будет так. Какое тебе дело? В чем проблема?
Ответ 2
Ну, это по крайней мере возможно:
public interface SelfImplementer<T extends SelfImplementer<T>> {
void method(T self);
}
Как вы можете видеть, объявление Generic немного похоже на бесконечную рекурсию, и я уверен, что если бы у Java не было стирания типа, это было бы - к счастью (?) все Generics на самом деле Objects
после компилятора обратился к ним, чтобы вы могли это сделать
public class Impl implements SelfImplementer<Impl> {
@Override
public void method(Impl self) {
System.out.println("Hello!");
}
}
и, как ожидалось, это
public static void main(String[] args) {
Impl impl = new Impl();
impl.method(impl);
}
выводит
Hello!
Ответ 3
Что вы хотите сделать, вероятно, что-то вроде этого:
public interface MyInterface <T extends A> {
public void method(T object) {
...
}
}
public class A implements MyInterface<A_or_class_extending_A>
{ ... }
Я надеюсь, что это помогло!