gpt4 book ai didi

java - 避免形式为 For> 的泛型类型

转载 作者:塔克拉玛干 更新时间:2023-11-03 03:02:28 27 4
gpt4 key购买 nike

我经常发现自己想要编写以下形式的通用类定义

public class Foo<ActualType extends Foo<ActualType>>

例如在这样的设置中:

public interface ChangeHandler<SourceType> {
public void onChange(SourceType source);
}


public class Foo<ActualType extends Foo<ActualType>> {

private final List<ChangeHandler<ActualType>> handlers = new ArrayList<>();

public void addChangeHandler(ChangeHandler<ActualType> handler) {
handlers.add(handler);
}

@SuppressWarnings("unchecked")
protected void reportChange() {
for (ChangeHandler<ActualType> handler: handlers)
handler.onChange((ActualType) this);
}
}


public class Bar extends Foo<Bar> {
// things happen in here that call super.reportChange();
}


public static void main(String[] args) throws IOException {

Bar bar = new Bar();
bar.addChangeHandler(new ChangeHandler<Bar>() {

@Override
public void onChange(Bar source) {
// Do something with the changed object
}
});
}

这里的 change-event 只是一个例子。这是一个更普遍的问题,每当我想允许父类(super class)为每个特定的子类提供“个性化”的功能时(不确定如何更好地表达这个......在示例中“个性化”之上的事实是 ChangeHandler 是用实际子类型 (Bar) 的对象调用的,而不是用父类(super class)的类型 (Foo) 调用处理程序)。

不知何故,这种方法对我来说似乎有点困惑。它实际上允许潜在的问题,因为没有什么能阻止我定义:

public class Baz extends Foo<Bar> { /* ... */ }

有没有更清洁的替代品?

chalice 是一些总是被定义为包含当前类的类型参数,比如 this.getClass() 的静态版本,它允许我写这样的东西:

public class Foo {

private final List<ChangeHandler<this.Class>> handlers = new ArrayList<>();

public void addChangeHandler(ChangeHandler<this.Class> handler) {
handlers.add(handler);
}

protected void reportChange() {
for (ChangeHandler<this.Class> handler: handlers)
handler.onChange(this);
}
}

对于 Bar 类型的类,this.Class 等于 Bar

最佳答案

这是一个非常抽象的问题。在我看来,对“如何使它更清洁”的简短回答是:只在需要的地方使用泛型。

public class List<T extends List<T>>

这是想表达什么(替代)?一个只允许持有(T 扩展)其他列表的列表,这些列表本身持有 Ts(列表),正如我们之前知道的那样,这些列表只允许持有......等等。有点像通告,我不明白你怎么会得到这样的结果?

public interface ChangeHandler<SourceType> {
public void onChange(SourceType source);
}

为什么要在这里使用泛型?如果您想要一个可以处理多种资源类型的更改处理程序,那么您可以创建一个所有实际源都继承自的父类(super class),或者创建一个由源实现的接口(interface)。这样您就可以准确指定源公开的内容。或者,源可以在通知时创建一个源对象,而不是传递“this”(那么它更像是一条消息)。例如:

public interface ChangeHandler {
public void onChange(Source source);
}

public abstract class Source {
private List<ChangeHandler> handlers;
protected int nr;
public Source(int nr) {
this.nr = nr;
}
public abstract Something getSomething();
public String toString() {
return "SRC" + nr;
}
...
private notify(int index) {
handlers.get(i).onChange(this);
}
}

public class Foo extends Source {
public Foo(int nr) {
super(nr);
}
public String toString() {
return super.toString() + "Foo";
}
public Something getSomething() {
return new Something();
}
}

你永远不需要施法……是吗?我不确定我是否理解这个问题。

关于java - 避免形式为 For<Actual Type extends Foo<Actual Type>> 的泛型类型,我们在Stack Overflow上找到一个类似的问题: https://stackoverflow.com/questions/30382847/

27 4 0
Copyright 2021 - 2024 cfsdn All Rights Reserved 蜀ICP备2022000587号
广告合作:1813099741@qq.com 6ren.com