我想为这两个类创建一个通用接口,但我不确定如何以正确的方式指定泛型。
public class ThingA implements Thing {
public ThingA createCopy(ThingA original);
}
public class ThingB implements Thing {
public ThingB createCopy(ThingB original);
}
我试过这个。
public interface Thing<V extends Thing<V>> {
public V createCopy(V original);
}
但是我仍然可以做这样的事情,这是不允许的。
public class ThingB implements Thing<ThingA> {
public ThingA createCopy(ThingA original);
}
答案 0 :(得分:6)
没有this
关键字泛型(也没有方法参数和返回值声明),因此您无法完全按照自己的意愿行事。
换句话说,接口将允许确保类中的所有方法都使用一致的类型,但不能引用类类型本身。
答案 1 :(得分:1)
这是不可能的。并不是Generics的用途。泛型用于类型安全,即避免强制转换。如果有人创建了一个以某种方式实现ThingB
的类Thing<ThingA>
,那就太好了。它完全是类型安全的。你为什么在乎?它如何阻碍你的工作?
答案 2 :(得分:0)
您在寻找
吗?public interface Thing<V> {
public V createCopy(V original);
}
?如果没有,你能否更详细地解释一下“为两个类创建一个通用接口”对你意味着什么?
答案 3 :(得分:0)
如果您可以自由使用扩展而不是实现,那么您可以这样做:
public interface Thing { ... }
public abstract class Copyable {
public final Copyable copy() {
Copyable clone = createCopy();
if (clone.getClass() != getClass())
throw new RuntimeException("Copy has wrong type!");
return clone;
}
protected abstract Copyable createCopy();
}
然后使用它:
public class Test extends Copyable implements Thing {
public String content = null;
@Override
public Copyable createCopy() {
Test clone = new Test();
clone.content = this.content;
return clone;
}
}
/*code somewhere*/ {
Test t1 = new Test();
t1.content = "Hello world!";
Test t2 = (Test)t1.copy();
System.out.println(t2.content);
}
这有一个问题,Copyable
不是界面。但是,如示例所示,可以毫不费力地使用它,但语言级别不支持使用的类检查。换句话说,createCopy
抽象方法不限于它复制的类,所有这些都取决于扩展Copyable
类的程序员或扩展它的类。
积极的一面是,如果你在对象上调用.copy()
,它必须返回与自身相同的对象。如果您愿意,可以返回null
而不是例外。然后你好或没什么。
但是,说实话,我真的不明白,为什么你的createCopy
本地方法有参数。
它可能是一个静态的方法...虽然我甚至无法想象会进入该代码块的内容:
static <X extends Thing> X copy(X object) { ... }
愿你可以将实践与静态通用方法结合起来,结果会变得更加友好:
public interface Thing extends Cloneable {
public static <X extends Thing> X copy(X thing) {
Object clone = thing.clone();
if (clone.getClass() != getClass())
throw new RuntimeException("Copy has wrong type!");
return (X)clone;
}
}
public class ThingA implements Thing {
public Object clone() { ... }
}
/*code somewhere*/ {
ThingA a1 = new ThingA();
ThingA a2 = Thing.copy(a1);
}
尽管如此,克隆方法受到异常而非语言限制的约束,但我认为这是最好的解决方案。