Kotlin扩展任何?.toString()

我一直在尝试在Kotlin中使用扩展函数。

class ExtensionExample() { var name: String? = null fun Any?.toString() : String { if (this == null) { return "Value is null" } return "Value is not null" } } 

当我打印如下所示的名称variables

 println(ExtensionExample().name.toString()) 

它应该打印像

 Value is null 

但它不像我预期的那样打印。 它只打印null

有人可以解释一下吗?

扩展函数有范围 。 这就是为什么它不能在ExtensionExample类之外访问。

通常,扩展function被定义为顶层function。 也就是说,他们倾向于属于一个阶级之外

您的toString扩展名在ExtensionExample定义。 这是可能的 ,但这意味着它只能在这个类的范围内使用 ,而且只能在这个类中使用

你的main方法可能是一个顶级函数(而不是该类的成员),所以它不能访问这个扩展函数。

只有其他成员可以访问这个扩展function:

 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) { ExtensionExample().foo() } 

打印"Value is null"

在线试用!

编译它的原因是被调用的toString方法是kotlin-stdlib中的Any?.toString方法。 也就是说, 这个方法已经存在了

fun Any?.toString(): String

返回对象的字符串表示forms。 可以用一个空的接收器来调用,在这种情况下,它返回字符串“null”。

将您的扩展function移出课程 。 你的扩展函数将会隐藏 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) { println(ExtensionExample().name.toString()) } 

打印"Value is null" ,如你所愿。

在线试用!


请注意,您不能使用扩展function隐藏成员函数。 那是,

 class Test { fun a() { println("a") } } fun Test.a() { println("b") } ... Test().a() 

会导致打印出“a”。

为什么你的Any?.toString工作(移出课后)的唯一原因是Any? 没有成员,因为它不是类,而是Any类的可空types。 已经存在的toString方法也是一个扩展,所以你的不被任何成员隐藏。

在类中定义一个扩展函数:

如果你想在ExtensionExample保留toString()的定义,你只能从那里使用它:

 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()) 

将打印

空值
里面:值是空的

在类之外定义一个扩展函数:

但如果你想在外面使用它,你必须把它移到外面:

 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()) 

将打印:

外部:值为空
里面:值是空的

如果一个类有一个成员函数,并且定义了一个具有相同接收器types,相同名称并适用于给定参数的扩展函数,则该成员总是获胜。

你的扩展方法不能影响AnyObject )类的内置toString方法。

至于在可空types上调用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 

另请参阅有关扩展解决方案的文档 。