Warning: file_get_contents(/data/phpspider/zhask/data//catemap/4/kotlin/3.json): failed to open stream: No such file or directory in /data/phpspider/zhask/libs/function.php on line 167

Warning: Invalid argument supplied for foreach() in /data/phpspider/zhask/libs/tag.function.php on line 1116

Notice: Undefined index: in /data/phpspider/zhask/libs/function.php on line 180

Warning: array_chunk() expects parameter 1 to be array, null given in /data/phpspider/zhask/libs/function.php on line 181
多个可能类型的Kotlin类型推断?_Kotlin - Fatal编程技术网

多个可能类型的Kotlin类型推断?

多个可能类型的Kotlin类型推断?,kotlin,Kotlin,我有一个函数,它接受两种可能类型的参数元数据:Metadata1或Metadata2。我正在尝试编写一个实用函数,它可以同时用于这两个方面,因为有大量的代码重用。它们都有一个DataPoint对象列表,每个对象都有name()方法 我认为在我的代码中,Kotlin会使用类型推断来知道dataPoints只能是两种都有DataPoint.name()方法的类型之一,但我得到了“未解析引用:name”。如何使此函数足够通用,以应用于Metadata1和Metadata2 var dataPoints

我有一个函数,它接受两种可能类型的参数
元数据
:Metadata1或Metadata2。我正在尝试编写一个实用函数,它可以同时用于这两个方面,因为有大量的代码重用。它们都有一个DataPoint对象列表,每个对象都有name()方法

我认为在我的代码中,Kotlin会使用类型推断来知道
dataPoints
只能是两种都有DataPoint.name()方法的类型之一,但我得到了“未解析引用:name”。如何使此函数足够通用,以应用于Metadata1和Metadata2

var dataPoints: List<Any>
if (metadata is Metadata1) {
    dataPoints = metadata.metadata1().dataPoints()
} else {
    dataPoints = (metadata as Metadata2).metadata2().dataPoints()
}
if (data.size > 1) {
    textView.test = dataPoints.fold("")
    { x, dataPoint ->
        x + dataPoint.name() + " \n" // unresolved reference: name
    }
}

var数据点:列表
if(元数据是元数据1){
dataPoints=metadata.metadata1().dataPoints()
}否则{
dataPoints=(元数据为Metadata2).Metadata2().dataPoints()
}
如果(data.size>1){
textView.test=dataPoints.fold(“”)
{x,数据点->
x+数据点.name()+“\n”//未解析的引用:name
}
}

这不是Kotlin独有的,静态类型的OOP语言就是这样工作的

数据点的类型为
List
Any
没有name()函数。你没有显示太多的代码,所以我不知道你有什么类型的对象

这是关于运行时与编译时的比较。编译器无法预测您将在运行时将哪些类型放入
列表
,因此您只能对其成员调用属于
任何
类的函数。想象一下,如果该列表包含一个没有name()函数的对象。如果编译器允许您调用name(),那么您将发生运行时崩溃。这就是为什么在尝试时会出现编译器时间错误

如果列表中有两种不同类型的对象,一种方法是创建一个它们都使用接口中的共享方法实现的接口。看起来是这样的:

interface Name {
    fun name()
}
将dataPoints更改为
List
,让您的数据类实现它,现在
dataPoint.name()
可以编译,因为列表中只允许使用带有name()函数的
name
类型的对象

var dataPoints: List<Name>
if (metadata is Metadata1) {
    dataPoints = metadata.metadata1().dataPoints()
} else {
    dataPoints = (metadata as Metadata2).metadata2().dataPoints()
}
if (data.size > 1) {
    textView.test = dataPoints.fold("")
    { x, dataPoint ->
        x + dataPoint.name() + " \n" // Compiles now
    }
}
var数据点:列表
if(元数据是元数据1){
dataPoints=metadata.metadata1().dataPoints()
}否则{
dataPoints=(元数据为Metadata2).Metadata2().dataPoints()
}
如果(data.size>1){
textView.test=dataPoints.fold(“”)
{x,数据点->
x+dataPoint.name()+“\n”//现在可以编译了
}
}

Metadata1和Metadata2类也有类似的问题,它们可能应该实现一个接口或扩展一个超类。

否,Kotlin没有联合类型。另外,您还声明了一个
列表
。这两个类是否有公共接口或超类?您应该创建一个接口(例如,定义了
name()
函数)供这两个类实现。
Metadata1
Metadata2
必须有一些共享的超类型:接口、类和密封类(这将保证它始终是这两个中的一个)…如果没有这一点,您基本上无法实现这一点。(好吧,您可以创建一个密封的类,该类包含
元数据1
元数据2
,但这会在调用方增加更多工作。)我最终解决了这个问题,将Metadata1和Metadata2的数据点映射到一个单一的共享类型,并将其作为共享类型参数直接传递到函数中。非常感谢!这两个类可能都有一个名为
name()的方法
,但只有当它们从同一类或接口继承时才是同一个方法。否则,它们是完全不同的、不相关的方法,只是拼写相同而已。