- iOS/Objective-C 元类和类别
- objective-c - -1001 错误,当 NSURLSession 通过 httpproxy 和/etc/hosts
- java - 使用网络类获取 url 地址
- ios - 推送通知中不播放声音
我有一个包含以下组件的项目:
public abstract class BaseThing {
public abstract <T extends BaseThing> ThingDoer<T, String> getThingDoer();
}
public class SomeThing extends BaseThing {
public ThingDoer<SomeThing, String> getThingDoer() {
return Things.getSomeThingDoer();
}
}
public class SomeOtherThing extends BaseThing {
public ThingDoer<SomeOtherThing, String> getThingDoer() {
return Things.getSomeOtherThingDoer();
}
}
public class Things {
public ThingDoer<SomeThing, String> getSomeThingDoer {
return getThingDoer(SomeThing.class);
}
public ThingDoer<SomeOtherThing, String> getSomeOtherThingDoer {
return getThingDoer(SomeOtherThing.class);
}
private <D extends ThingDoer<T, String> D getThingDoer(Class<T> clazz) {
//get ThingDoer
}
}
public class ThingDoer<T, V> {
public void do(T thing) {
//do thing
}
}
public class DoThing {
private BaseThing thing;
public void doIt() {
thing.getThingDoer().do(thing);
}
}
我在 SomeThing.getThingDoer()
中收到编译器警告上面写着:
Unchecked overriding: return type requires unchecked conversion.
Found
ThingDoer<SomeThing, String>
, requiredThingDoer<T, String>
一切都编译得很好,虽然我没有机会测试 DoThing.doIt()
然而,我没有理由相信它不会奏效。
我的问题是,这会中断吗?是否有更好的方法来做到这一点?我可以做 DoThing
一个基类,并且都有子类 SomeThing
和 SomeOtherThing
但这似乎不是很优雅。
编辑:我想避免制作 BaseThing
通用。
最佳答案
让我们先看看你的BaseThing
您不想使其通用的类:
public abstract class BaseThing {
public abstract <T extends BaseThing> ThingDoer<T, String> getThingDoer();
}
这不是泛型类,但它包含一个泛型方法。通常,像这样的通用方法被设计成类型 <T>
由编译器根据方法的某些参数进行绑定(bind)。例如:public <T> Class<T> classOf(T object)
.但在你的情况下,你的方法没有参数。这也有点常见,在方法的实现返回一些“通用”通用(我的术语)的情况下,就像来自 Collections
的这个方法一样。实用程序类:public <T> List<T> emptyList()
.此方法不带参数,但类型 <T>
将从调用上下文推断;它仅有效,因为 emptyList()
的实现返回一个在所有情况下都是类型安全的对象。由于类型删除,该方法实际上并不知道 T
的类型当它被调用时。
现在,回到您的类(class)。当您创建 BaseThing
的这些子类时:
public class SomeThing extends BaseThing {
public ThingDoer<SomeThing, String> getThingDoer() {
return Things.getSomeThingDoer();
}
}
public class SomeOtherThing extends BaseThing {
public ThingDoer<SomeOtherThing, String> getThingDoer() {
return Things.getSomeOtherThingDoer();
}
}
在这里,您想覆盖 abstract
来自基类的方法。 Java 中允许覆盖返回类型,只要返回类型在原始方法的上下文中仍然有效。例如,您可以覆盖返回 Number
的方法使用始终返回 Integer
的特定实现对于那个方法,因为Integer
是一个 Number
.
然而,对于泛型,一个 List<Integer>
不是 List<Number>
.因此,虽然您的抽象方法被定义为返回 ThingDoer<T, String>
(对于某些 T extends BaseThing
),您返回的重载 ThingDoer<SomeThing, String>
和 ThingDoer<SomeOtherThing, String>
通常与一些未知的 T
不兼容尽管 SomeThing
和 SomeOtherThing
都从 BaseThing
延伸.
调用者(来自抽象 API)期望一些未知的、不可执行的 T
您的任何一个具体实现都不能保证满足这一点。事实上,您的具体重载不再是通用的(它们返回特定的、静态绑定(bind)的类型参数)并且与抽象类中的定义冲突。
编辑:定义抽象方法的“正确”方式(没有警告)应该是这样的:
public abstract ThingDoer<? extends BaseThing, String> getThingDoer();
这让调用者清楚地知道它得到了一个 ThingDoer
它的第一个类型参数绑定(bind)到扩展 BaseThing
的东西 (因此它可以像使用 BaseThing
一样使用它)但是调用者不会知道抽象 API 访问时的具体实现。
编辑 #2 - 我们在聊天中讨论的结果......
OP 的原始示例用法是:
BaseThing thing = /* ... */;
thing.getThingDoer().do(thing);
请注意 thing
是如何相同的引用被传递回从同一事物的 getThingDoer()
返回的对象中的方法。方法。 getThingDoer()
返回的对象需要紧密绑定(bind)到 thing
的具体实现类型(根据OP)。对我来说,这闻起来像是破损的封装。
相反,我建议将逻辑操作公开为 BaseThing
的一部分API 并将委托(delegate)封装到 ThingDoer
作为内部实现细节。生成的 API 类似于:
thing.doTheThing();
实现起来有点像:
public class SomeThing extends BaseThing {
@Override public void doTheThing() {
Things.getSomeThingDoer().do(this);
}
}
public class SomeOtherThing extends BaseThing {
@Override public void doTheThing() {
Things.getSomeOtherThingDoer().do(this);
}
}
关于Java 未经检查的重写返回类型,我们在Stack Overflow上找到一个类似的问题: https://stackoverflow.com/questions/23645753/
我需要根据需要动态设置文本区域,但它不想正常工作。 JQuery 会自行检查,但无法检查是否已检查。但是当您在第二个单选框内单击时,始终需要文本区域。我尝试了很多次让它工作,但它仍然有问题。我添加了“
我需要在 Django 中进行 API 调用(某种形式),作为我们所需的自定义身份验证系统的一部分。用户名和密码通过 SSL 发送到特定 URL(对这些参数使用 GET),响应应该是 HTTP 200
我将在我的可移植 C 代码中使用 #warning 来生成编译时警告。但并非所有平台都支持 #warning。有什么方法可以找到该平台是否支持 #warning。 #ifdef warning
我编写了一个函数来检查某个数字是否存在于某个区间内。停止搜索的最佳方法是什么?这个: for (i = a; i <= b; i++) { fi = f(i); if (fi == c) {
我想知道在 c 中是否有一种方法可以检查,例如在 for 函数中,如果变量等于或不等于某些字符,而不必每次都重复进行相等性检查。如果我没记错的话,以这种方式检查相等性是不正确的: if (a == (
我有如下日志功能 void log_error(char * file_name, int line_num, int err_code) { printf("%s:%d:%s\n", fil
使用 ssh-keygen 生成的 key 对在 macOS 上可以有不同的格式。 macOS 可读的标准 PEM ASN.1 对象 SecKey API 带有文本标题的 PEM OpenSSH ke
我正在尝试编写一个 excel if 语句。我不熟悉使用 Excel 具有的所有额外功能。我正在使用一个名为 importXML() 的函数.我正在尝试检查我正在使用的函数是否生成“#VALUE!”错
有没有办法检查是否没有 AIO 写入给定文件?我在我的 Unix 类(class)上制作了一个项目,该项目将是一个上下文无关(基于 UDP)的国际象棋服务器,并且所有数据都必须存储在文件中。应用程序将
我有一个如下所示的函数: public Status execute() { Status status = doSomething(); if (status != Stat
我正在使用 Composer,我不希望 PhpStorm 在 vendor 文件夹上运行任何错误检查或检查,因为它对 vendor/中的某些代码显示误报composer/autoload_static
Chapel 的一个很好的特性是它区分了数组的域和它的分布。检查两个数组是否具有相同的域和分布(通常想要的)的最佳方法是什么? 我能看到的最好的方法是检查 D1==D2和 D1.dist==D2.di
在我的 JavaScript 函数中,我为所有输入、文本区域和选择字段提供实际值作为 initial_value: $('input, textarea, select').each(function
我正在编写一个分解为几个简单函数的 PHP 类。在构造函数中,它调用另一个名为 processFile 的函数。该函数调用 5 个私有(private)函数并进行检查。如果检查失败,它会将消息分配给
这个问题已经有答案了: How to detect if user it trying to open a link in a new tab? (2 个回答) 已关闭 7 年前。 我认为 JavaS
我正在浏览我们的代码库并看到很多这样的测试: declare @row_id int = ... declare @row_attribute string select @row_attribu
我正在声明一个用作比较的函数。我的问题是: 为什么条件充当语句? 为什么第 4 行可以工作,而第 5 行却不行? 我知道这段代码不切实际且未使用,但为什么编译器允许这种语法? 谷歌没有找到答案。但话又
到目前为止,我有一个带有空文本字段的 PHP Kontaktform,并使用以下命令检查了所需的字段: $name = check_input($_POST['name'], "请输入姓名。"); 现
目前,我能想到的合理检查的唯一方法没有臃肿的逻辑: if ( $value > 0 ) { // Okay } else { // Not Okay } 有没有更好的办法? 最佳答案
我正在尝试运行一个脚本,如果 i 存在(意味着存在 i 值,任何值)或其他部分,我希望运行其中的一部分如果i没有值就运行,有人可以启发我吗? 我说的是 for 循环,比如 for (var i=0;
我是一名优秀的程序员,十分优秀!