我一直在尝试在Kotlin中使用扩展功能。
class ExtensionExample() {
var name: String? = null
fun Any?.toString() : String {
if (this == null) {
return "Value is null"
}
return "Value is not null"
}
}
当我打印名称变量时,如下所示
println(ExtensionExample().name.toString())
它应该打印像
Value is null
但它没有像我预期的那样打印。它只打印null
。
有人可以解释一下吗?
答案 0 :(得分:5)
Extension functions有scopes。这就是为什么它不能在ExtensionExample
类之外访问。
通常,扩展函数被定义为顶级函数。也就是说,它们往往属于之外的。
您的toString
扩展程序在ExtensionExample
内定义。 This is possible,但它表示仅在此课程范围内可用,且此课程仅。
您的main
方法可能是顶级函数(而不是该类的成员),因此无法访问此扩展函数。
只有其他成员才能访问此扩展功能:
class ExtensionExample {
var name: String? = null
fun Any?.toString(): String {
return if (this == null) "Value is null" else "Value is not null"
}
fun foo() {
println(name.toString())
}
}
fun main(args: Array<String>) {
ExtensionExample().foo()
}
打印"Value is null"
它编译的原因是被调用的toString
方法是Any?.toString
中的kotlin-stdlib方法。也就是说,此方法已存在。
fun Any?.toString(): String
返回对象的字符串表示形式。可以使用null接收器调用,在这种情况下,它返回字符串&#34; null&#34;。
将您的扩展程序功能移出课堂。然后,您的扩展功能将隐藏 stdlib的扩展名,并且未明确导入kotlin.toString
的同一个包中的任何调用都将使用您的函数。
以下是您的代码的工作版本:
class ExtensionExample {
var name: String? = null
}
fun Any?.toString(): String {
return if (this == null) "Value is null" else "Value is not null"
}
fun main(args: Array<String>) {
println(ExtensionExample().name.toString())
}
根据需要打印"Value is null"
。
请注意,您无法使用扩展功能隐藏成员函数。也就是说,
class Test {
fun a() {
println("a")
}
}
fun Test.a() {
println("b")
}
...
Test().a()
将导致&#34; a&#34;被打印。
Any?.toString
工作(移出课程后)的唯一原因是 Any?
没有成员因为它不是一个类,而是一个可空的使用类Any
键入。现有的toString
方法也是一种扩展,因此您的任何成员都不会隐藏它。
答案 1 :(得分:2)
在类中定义扩展函数:
如果您想将toString()
的定义保留在ExtensionExample
内,您可以仅从那里使用它:
class ExtensionExample() {
var name: String? = null
// uses the toString() extension function defined in ExtensionExample
fun useToString() = name.toString()
fun Any?.toString(): String {
if (this == null) {
return "inside: Value is null"
}
return "inside: Value is not null"
}
}
此
// uses the version of toString() defined in the Kotlin Standard library
println(ExtensionExample().name.toString())
// uses the inside version of toString()
println(ExtensionExample().useToString())
将打印
空
inside:值为null
在课堂外定义扩展功能:
但是如果你想在外面使用它,你必须把它移到外面:
class ExtensionExample() {
var name: String? = null
// uses the toString() extension function defined in ExtensionExample
fun useToString() = name.toString()
fun Any?.toString(): String {
if (this == null) {
return "inside: Value is null"
}
return "inside: Value is not null"
}
}
fun Any?.toString(): String {
if (this == null) {
return "outside: Value is null"
}
return "outside: Value is not null"
}
此
// uses the outside version of toString() which overrides the one from the Kotlin Standard library
println(ExtensionExample().name.toString())
// uses the inside version of toString()
println(ExtensionExample().useToString())
将打印:
外:价值无效
inside:值为null
答案 2 :(得分:0)
如果一个类有成员函数,并且定义了一个扩展函数,它具有相同的接收者类型,相同的名称并且适用于给定的参数,则该成员总是获胜。
您的扩展程序无法隐藏toString
(Any
)类上的内置Object
方法。
至于在可空类型上调用toString
,此方法已经在Kotlin运行时中:
/**
* Returns a string representation of the object. Can be called with a null receiver, in which case
* it returns the string "null".
*/
public fun Any?.toString(): String
另请参阅docs有关扩展程序的解决方案。