问题描述
我真的可以用您的帮助来解释此功能。
我有一个包含2个字符串值,一个国家名称和一个货币的国家/地区枚举。练习是使用2个字符串输入,检查枚举是否包含国家/地区,然后比较其货币,并相应返回true或false。我设法用2 for循环和2 ifs来做到这一点,但是我知道这并不理想。
然后,我尝试使用contains()
和valueOf(input)
,但是当输入不在枚举中时,它将为valueOf()
抛出非法参数异常
if (values().contains(valueOf(country1.toupperCase())) && values().contains(valueOf(country2.toupperCase()))) {
return valueOf(country1.toupperCase()).currency == valueOf(country2.toupperCase()).currency
} else return false
我在这里搜索,发现了一个我不太了解的valueOfOrNull()
方法
inline fun <reified T : Enum<T>> enumValueOfOrNull(country: String): T? {
return enumValues<T>().find { it.name == country.toupperCase() }
}
您能帮我解释一下这是如何工作的吗?我不知道内联的,经过修饰的T:Enum是如何工作的,它返回什么。
另外,我刚刚开始学习lambda,因此我对.find {}
部分有了基本的了解,但是我可以对it
感谢您的所有帮助,非常感谢。
解决方法
在Kotlin中,inline
functions使它们的主体在编译时发生转换,并且很好地在每个调用站点中内联。尽管这需要编译器进行更多工作并导致更大的二进制文件,但是inline
函数在某种程度上更灵活,因为与将它们的主体全部编译为一个字节码相比,编译器从每个调用位置获取更多的附加信息,并且可能会将其嵌入到内联主体中,从而根据调用产生不同的结果。嵌入到转换后的内联函数主体中的此类附加数据的一个示例是从调用站点传递给函数的lambda,允许non-local control flow。
编译器可以为特定调用站点转换主体的另一种方法是通过嵌入来自调用站点的实际泛型类型参数。为所有调用站点生成单个已编译的函数主体时,编译器无法生成任何将实际类型参数考虑在内的代码,例如foo is T
检查。换句话说,实际的type arguments are erased。但是,对于每个单独的呼叫站点,都可以使用内联主体,这成为可能。该功能称为reified
type parameters。
然后,enumValues
是编译器专门处理的内在函数,可以在作为Enum
(每个enum class
的子类型)的类型化参数上调用该函数,并且然后在内联函数主体中将有一个返回枚举值的调用。这不是唯一在内联过程中与经过修饰的类型参数一起使用的内在函数:typeOf
也会这样做,并且会产生一个KType
令牌,可以用来内省一个实际的类型参数。