扩展函数有作用域。这就是为什么它在ExtensionExample
类之外不可访问的原因。
通常,扩展函数被定义为顶级函数。也就是说,它们往往属于类之外。
您的toString
扩展是在ExtensionExample
内定义的。这是可能的,但这意味着它只在该类的范围内可用,而且仅限于该类。
您的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
方法是来自kotlin-stdlib的Any?.toString
方法。也就是说,这个方法已经存在。
fun Any?.toString(): String
返回对象的字符串表示形式。可以使用空接收器调用,在这种情况下,它将返回字符串"null"。
将您的扩展函数移出类。然后,您的扩展函数将隐藏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()
这将导致打印出 "a"。
你的 Any?.toString
之所以能够工作(在被移出类之后)仅仅是因为 Any?
没有成员,因为它不是一个类,而是一个带有类 Any
的可空类型。已经存在的 toString
方法也是一个扩展方法,因此你的方法不会被任何成员隐藏。