泛型类型的args具体是哪个扩展类?
我想要一个实现接口的类,该接口将特定的子类指定为参数。
public abstract Task implements TaskStatus<Task> { TaskStatus<T> listener; protected complete() { // ugly, unsafe cast callback.complete((T) this); } } public interface TaskStatus<T> { public void complete(T task); }
但是我要保证使用的type-arg不仅仅是扩展该任务的特定类,而不仅仅是任务or。
因此,我想出的最好的方法是:
public abstract Task<T extends Task> implements TaskStatus<T> { }
我们可以通过编写以下内容来扩展它:
public class MyTask extends Task<MyTask> { }
但这也是有效的:
public class MyTask extends Task<SomeOtherTask> { }
并且回调的调用将与ClassCastException一起炸毁。那么,这种方法是错误的又是折断的,还是有一种正确的方法使我错过了呢?
解决方案
目前尚不清楚我们要在"任务"内部执行的操作。但是,如果我们按如下方式定义通用类Task <T>
:
class Task<T extends Task<T>> { ... }
可能有以下两种:
class MyTask extends Task<MyTask> { ... } class YourTask extends Task<MyTask> { ... }
但是以下是禁止的:
class MyTask extends Task<String> { ... }
以上"任务"的定义使用了F界多态性,这是一个相当高级的功能。我们可以查看研究论文"面向对象编程的F界多态性"以获取更多信息。
我在理解我们要通过此方法完成的工作时遇到了一些麻烦。我们能否提供更多详细信息?
我对代码的阅读表明,我们有这些任务将被子类化,并且在任务完成后,执行线程将在该任务上调用complete()。此时,我们想调用一个回调并将其传递给子类对象。我认为这是问题所在。我们正在尝试将有关潜在子类的知识放入抽象类中,这是禁止的。
这也引发了一个问题,如果可以进行此调用,那么与超类不同的子类的回调将如何处理?
我建议添加一个getThis,它应该返回正确键入的内容。当然,subclas可能行为不当,但这始终是事实。我们避免的是强制转换和ClassCastException的可能性。
public abstract class Task<THIS extends Task<THIS>> { private TaskStatus<THIS> callback; public void setCallback(TaskStatus<THIS> callback) { this.callback = callback==null ? NullCallback.INSTANCE : callback; } protected void complete() { // ugly, unsafe cast callback.complete(getThis()); } protected abstract THIS getThis(); } public interface TaskStatus<T/* extends Task<T>*/> { void complete(T task); } public class MyTask extends Task<MyTask> { @Override protected MyTask getThis() { return this; } }
建设者经常会遇到这个问题。
我真的只有在构造函数中强制使用arg类型时才能看到此方法。通过。内省和Class.getSuperType(),我们可以检查args类型,并验证arg类型与该类匹配。
遵循以下原则:
assert getClass() == ((ParameterizedType) getSuperType()).getTypeArguments()[0];
(这是我的脑袋,请检查JavaDocs进行验证)。
我不确定在代码中在哪里创建回调。我们已经在顶部省略了它的声明。
另一种方法是删除不安全的演员表,例如atm。我看不到有完整的流程可以找出为什么我们需要不安全的演员表。