Kotlin扩展任何?.toString()

时间:2017-12-08 19:26:55

标签: kotlin kotlin-android-extensions

我一直在尝试在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

有人可以解释一下吗?

3 个答案:

答案 0 :(得分:5)

Extension functionsscopes。这就是为什么它不能在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"

Try it online!

它编译的原因是被调用的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"

Try it online!

请注意,您无法使用扩展功能隐藏成员函数。也就是说,

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)

  

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

您的扩展程序无法隐藏toStringAny)类上的内置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有关扩展程序的解决方案。