kotlin - Ununderstood type variance using kotlin variance
问题描述
I'm using generics to not reuse code and I' running into a lack of understanding for type generics. I have a class Writer (java code from another library).
public class Writer<T>
A class FileWriter (java code from another library)
public class FileWriter<D>{
FileWriter(Writer<D> writer){
this.writer=writer
}
public void append(D datum){
//Does something
}
}
Now I'm initiating this in kotlin:
val writer = FileWriter(Writer(AGenratedJavaClassThatIMplementsSpecificRecord::class.java))
I can now call writer.append with AGenratedJavaClassThatIMplementsSpecificRecord(). It works just fine
I would like to pass this writer to a function.
funDoSomethingExtra(writer: FileWriter<in SpecificRecord>)
This gives me an error that I do not understand.
Type mismatch: inferred type is FileWriter<AGenratedJavaClassThatIMplementsSpecificRecord!>! but FileWriter<in SpecificRecord> was expected
Changing this to
funDoSomethingExtra(writer: FileWriter<out SpecificRecord>)
Makes writers.append give the error
Required Nothing, found AGenratedJavaClassThatIMplementsSpecificRecord.
Without the use of methods, all works fine. Which details Am I missing? It is probably something small,
Kind regards, Jelmew
解决方案
这行代码:
val writer = FileWriter(Writer(AGenratedJavaClassThatIMplementsSpecificRecord::class.java))
没有指定 FileWriter 的类型,所以它是从你的参数推断给构造函数的,所以类型writer
是FileWriter<AGenratedJavaClassThatIMplementsSpecificRecord>
.
您的签名funDoSomethingExtra(writer: FileWriter<in SpecificRecord>)
对于调用writer
对 aSpecificRecord
或 的子类型执行某些操作的方法是正确的SpecificRecord
。但是,您的
FileWriter<AGenratedJavaClassThatIMplementsSpecificRecord>
不能转换为 aFileWriter<in SpecificRecord>
因为AGenratedJavaClassThatIMplementsSpecificRecord
是 的子类型SpecificRecord
,而不是超类型。编译器知道您的文件编写器可以使用AGenratedJavaClassThatIMplementsSpecificRecord
,但它不知道它可以使用不太具体的类型SpecificRecord
。您有可能调用超类型中不存在的子类型的某些函数。
所以为了能够将你的 writer 传递给这个函数,它需要是 a FileWriter<SpecificRecord>
or FileWriter<in SpecificRecord>
。在已经分配了它的类型之后,您不能安全地转换它,但是您可以在声明站点为其分配正确的类型,而不是让编译器尝试推断它:
val writer: FileWriter<SpecificRecord> = FileWriter(Writer(AGenratedJavaClassThatIMplementsSpecificRecord::class.java))
推荐阅读
- html - Glyphicon-shopping-cart 不显示 iCON
- java - 写入带有子文件夹的新文件时自动创建整个路径
- c# - MSSQL CLR 函数 webreqest 401 未授权
- ios - FirebaseAnalytics:将事件记录到多个项目
- powershell - Powershell Add-Content 未添加到文件末尾
- php - Laravel 的返回值预计为 'illuminate\Http\Response',返回 'string'
- react-native - React-native-image-picker:如何以网格方式直接访问画廊图像
- powershell - Azure AD - 使用 SP 创建应用注册及其凭据
- python-3.x - 美丽的汤。如何在一次搜索中找到具有特定属性但属性值不同的标签?
- python - 如何用 100k 数据样本泛化基于序列的模型?