Допустим, нам надо сделать интерфейс, который бы позволял объекту копировать себя в объекты его (или ниже по наследованию) класса. Простейшая реализация будет в таком духе:
import org.junit.Test;
import org.junit.internal.runners.JUnit4ClassRunner;
import org.junit.runner.RunWith;
@RunWith(JUnit4ClassRunner.class)
public class TestGenerics {
public static interface Copyable {
public void copy(Copyable c);
}
public static class A implements Copyable {
private String aField = "--A--";
protected void innerCopy(Copyable c) {
A a = (A)c;
System.out.println(a.aField);
}
public void copy(Copyable c) {
innerCopy(c);
}
}
public static class B extends A {
private String bField = "--B--";
protected void innerCopy(Copyable c) {
B b = (B)c;
super.innerCopy(b);
System.out.println(b.bField);
}
}
@Test
public void testCopy() {
Copyable b1 = new B();
Copyable b2 = new B();
b1.copy(b2);
}
}
Я решил попробовать пошаманить с generic-ами и смог добиться того же результата таким образом:
import org.junit.Test;
import org.junit.internal.runners.JUnit4ClassRunner;
import org.junit.runner.RunWith;
@RunWith(JUnit4ClassRunner.class)
public class TestGenerics {
public static interface Copyable<T> {
public void copy(T t);
}
public static class A<T extends A<?>> implements Copyable<T> {
private String a = "--A--";
public void copy(T t) {
System.out.println(t.a);
}
}
public static class B<T extends B<?>> extends A<T> {
private String b = "--B--";
public void copy(T t) {
super.copy(t);
System.out.println(t.b);
}
}
@Test
@SuppressWarnings("unchecked")
public void testCopy() {
Copyable b1 = new B();
Copyable b2 = new B();
b1.copy(b2);
}
}
Но разобраться с предупреждениями о том что generic использован как raw type не удалось никак, кроме использования @SuppressWarnings("unchecked").
Вопрос: насколько второй вариант "идеологически" правильный и есть ли способ "честно" избавиться от предупреждений?
Здравствуйте, ojow, Вы писали:
[skipped]
Это вы автор вот этого:
Overriding Java generic methods?
Здравствуйте, ojow, Вы писали:
[skipped]
Не очень кошерно, но может так?
package ru.rsdn.generics;
import org.junit.Test;
public class TestGenerics {
public interface Copyable<T extends Copyable<? super T>> {
void copy(T t);
}
public class A implements Copyable<A> {
protected final String a = "--A--";
public void copy(A t) {
System.out.println(t.a);
}
}
public class B extends A {
private final String b = "--B--";
// it's not override
public void copy(B t) {
super.copy(t);
System.out.println(t.b);
}
}
@Test
public void testCopy() {
final A a0 = new A();
final A a1 = new A();
a0.copy(a1);
final A a = new A();
final B b = new B();
a.copy(b);
final B b0 = new B();
final B b1 = new B();
b0.copy(b1);
}
}
Здравствуйте, rsn81.
Во-первых, обращаться с объектами хочется по интерфейсу — собственно на то он и нужен.
Во-вторых, если в процессе наследования перестать параметризоваться, то дальше не получится перекрывать этот метод, будет только перегрузка, которая возвращает нас к привидению типов и первому из предложенных мной вариантов.