在客户端代码中使用类型处理多个 类
Handling multiple Classes with Types in client code
假设我有以下类
class A {}
class B {}
abstract class ParentClass<T> {
abstract void accept(T t);
}
class Child1 extends ParentClass<A> {
void accept(A a) {}
}
class Child2 extends ParentClass<B> {
void accept(B b) {}
}
现在,如果我有一个客户端代码,我希望将 child1 和 child2 的两个实例都映射到映射中的一个字符串(并且)还使用 accept 方法,这似乎是不可能的,我明白了为什么。有更好的解决方法吗?
我的客户端代码看起来像,
class Client {
Map<String, ParentClass<?>> map = new HashMap<>();
public Client() {
map.put("C1", new Child1());
map.put("C2", new Child2());
}
void callAccept(String type, Object o) {
map.get(type).accept(o); //error
}
}
#更新1
在示例中添加 return 类型,因为我在手机上输入问题时错过了。
“更好”取决于您想要实现的目标。据我了解你的问题,你只是希望能够编译代码并理解它。许多变化都是可能的,“最佳”取决于您要解决的业务问题。
没有代码可能解决的业务问题,这里是编译没有错误的代码。我修复了您代码中的几个错误:
// ParentClass.java
class Base {}
class A extends Base {}
class B extends Base {}
abstract class ParentClass<T> {
abstract ParentClass<?> accept(Base base);
}
class Child1 extends ParentClass<A> {
/* No idea what this is supposed to do,
so just return something type-compatible */
ParentClass<A> accept(Base base) { return this; }
}
class Child2 extends ParentClass<B> {
/* No idea what this is supposed to do,
so just return something type-compatible */
ParentClass<B> accept(Base base) { return this; }
}
ParentClass
,一个容器,被子class编辑为Child1
和Child2
。
上面的 Base
是 ParentClass
subclasses 中包含的有效载荷的基础 class。因为容器 class (ParentClass
) 是 subclassed,所以你需要一个基础 class 作为有效载荷,你希望能够混合和匹配有效载荷。
// Client.java
import java.util.HashMap;
import java.util.Map;
class Client {
Map<String, ParentClass<?>> map = new HashMap<>();
public Client() {
map.put("C1", new Child1());
map.put("C2", new Child2());
}
void callAccept(String type, Base base) {
map.get(type).accept(base);
}
}
Java、Scala、Haskell 和其他语言使用 type theory, specifically category theory 来精确定义允许的内容。实际上,在不迷失数学的情况下,上面的一般准则是使用泛型的一些注意事项。
有关更多信息,请阅读 Joshua Bloch 的“Effective Java”中关于通用容器的部分。不信他提范畴论,挺好的
如果您对“恰到好处”类型理论感兴趣,请阅读 covariant types。
假设我有以下类
class A {}
class B {}
abstract class ParentClass<T> {
abstract void accept(T t);
}
class Child1 extends ParentClass<A> {
void accept(A a) {}
}
class Child2 extends ParentClass<B> {
void accept(B b) {}
}
现在,如果我有一个客户端代码,我希望将 child1 和 child2 的两个实例都映射到映射中的一个字符串(并且)还使用 accept 方法,这似乎是不可能的,我明白了为什么。有更好的解决方法吗?
我的客户端代码看起来像,
class Client {
Map<String, ParentClass<?>> map = new HashMap<>();
public Client() {
map.put("C1", new Child1());
map.put("C2", new Child2());
}
void callAccept(String type, Object o) {
map.get(type).accept(o); //error
}
}
#更新1 在示例中添加 return 类型,因为我在手机上输入问题时错过了。
“更好”取决于您想要实现的目标。据我了解你的问题,你只是希望能够编译代码并理解它。许多变化都是可能的,“最佳”取决于您要解决的业务问题。
没有代码可能解决的业务问题,这里是编译没有错误的代码。我修复了您代码中的几个错误:
// ParentClass.java
class Base {}
class A extends Base {}
class B extends Base {}
abstract class ParentClass<T> {
abstract ParentClass<?> accept(Base base);
}
class Child1 extends ParentClass<A> {
/* No idea what this is supposed to do,
so just return something type-compatible */
ParentClass<A> accept(Base base) { return this; }
}
class Child2 extends ParentClass<B> {
/* No idea what this is supposed to do,
so just return something type-compatible */
ParentClass<B> accept(Base base) { return this; }
}
ParentClass
,一个容器,被子class编辑为Child1
和Child2
。
Base
是 ParentClass
subclasses 中包含的有效载荷的基础 class。因为容器 class (ParentClass
) 是 subclassed,所以你需要一个基础 class 作为有效载荷,你希望能够混合和匹配有效载荷。
// Client.java
import java.util.HashMap;
import java.util.Map;
class Client {
Map<String, ParentClass<?>> map = new HashMap<>();
public Client() {
map.put("C1", new Child1());
map.put("C2", new Child2());
}
void callAccept(String type, Base base) {
map.get(type).accept(base);
}
}
Java、Scala、Haskell 和其他语言使用 type theory, specifically category theory 来精确定义允许的内容。实际上,在不迷失数学的情况下,上面的一般准则是使用泛型的一些注意事项。
有关更多信息,请阅读 Joshua Bloch 的“Effective Java”中关于通用容器的部分。不信他提范畴论,挺好的
如果您对“恰到好处”类型理论感兴趣,请阅读 covariant types。