dart - Dart - 实现一个带有参数的类方法作为实现的类
问题描述
我正在开发外部库。假设我有不同的记录器类实现,我创建ILogger
了这些类可以实现的抽象类。
我也有各种日志对象的实现,我想遵守ILog
抽象类,所以我也公开了它。
问题是当我ILogger
使用它ILog
作为其中一种方法的参数时。我会假设我实现的任何记录器类(实现ILogger
)都将接受任何作为日志类(实现ILog
)的参数。
请参阅下面的受限示例:
abstract class ILog {
const LogImpl({required this.id});
final String id;
}
class Log implements ILog {
const Log({required this.id});
final String id;
}
abstract class ILogger {
void writeLog({
required LogImpl log,
required bool persist,
});
}
class Logger implements ILogger {
void writeLog({
required Log log,
required bool persist,
}) {
print('writing $log with persistence? $persist');
}
}
void main() {
final logger = Logger();
final log = Log(id: 'abcd-1234');
logger.writeLog(log: log, persist: true)
}
为此,我得到错误:
Error: The parameter 'log' of the method 'Logger.writeLog' has type 'Log', which does not match the corresponding type, 'ILog', in the overridden method, 'ILogger.writeLog'.
有没有办法在不求助于泛型的情况下解决这个问题?我的日志对象ILog
需要是抽象类而不是扩展的常规类的原因是技术性的。我的序列化库之一使用源代码注释,这意味着该注释不能成为库的一部分(因为不同应用程序的注释可能不同)。
解决方案
该程序无法编译,因为它不健全。Dart 和一般的面向对象编程基于子类型可替换性。如果您的代码适用于某个类型的实例,那么它也适用于子类型的实例——子类型可以替代超类型。
Logger
'writeLog
方法不是ILogger
'方法的有效覆盖writeLog
。后者接受一个ILog
作为参数,并且为了能够替代它的子类型,它也需要接受一个ILog
。但是,它只接受 a ,它是一个Log
子类型,而不接受.ILog
一种替代方法是承认您正在编写的内容不合理,并告诉编译器无论如何都要接受它:
class Logger implements ILogger {
void writeLog({
required covariant Log log,
required bool persist,
}) {
print('writing $log with persistence? $persist');
}
}
这里covariant
告诉编译器你知道Log
不满足的超类参数类型ILog
,但是没关系。你知道你在做什么,没有人会用不合适的东西来调用这个函数Log
。(如果他们仍然这样做,它会抛出一个错误)。
我可能会推荐的另一种选择是根据Log
它使用的参数化您的类:
abstract class ILogger<L extends ILog> {
void writeLog({
required L log,
required bool persist,
});
}
class Logger implements ILogger<Log> {
void writeLog({
required Log log,
required bool persist,
}) {
print('writing $log with persistence? $persist');
}
}
这样, theLogger
就不必替换所有 ILogger
的 s,只替换ILogger<Log>
,它可以很好地做到这一点。(好吧,就像固有的不健全的协变泛型所允许的那样健全,但是如果你传递了不是实例的东西,程序将编译并抛出。)Log
在这两种情况下,编译器都会知道 a 的参数Logger
必须是 a Log
。Logger
在这两种情况下,您都可以通过将 the 强制转换为超类型ILogger
/来欺骗程序ILogger<ILog>
,然后传入一个ILog
to writeLog
,但要绕过类型系统至少需要一点努力。
推荐阅读
- wordpress - 如何创建包含 YouTube 嵌入视频的 WordPress 厚盒响应式响应?
- asp.net-core - 当前上下文中不存在名称“SqlServerValueGenerationStrategy”
- python - 这是列表开始的限制吗?
- python - Python 的 len() 内置 O(1) 时间复杂度背后的秘密是什么
- scala - 多次使用prepared statement,提示Cassandra Querying Reducing Performance
- java - Spring 5 LDAP 身份验证和 JWT 令牌作为响应
- firefox-addon - 是否可以在 Firefox Quantum 中查看上传百分比
- java - Java 的 BouncyCastle 并不总是验证 OpenSSL ECDSA 签名
- function - filesystemwatcher事件函数powershell中的访问函数
- node.js - 运行 MEAN 应用程序时出现“无默认引擎”错误