【问题标题】:How to write an extension fun to append a string in Kotlin?如何编写扩展乐趣以在 Kotlin 中附加字符串?
【发布时间】:2018-07-26 19:14:29
【问题描述】:

我正在写一个关于扩展乐趣的练习代码。

我计划为 String 添加一个扩展 fun myAdd,它接受 lambda fun 并将 lambda 的结果附加到 String。

例如:

var cc="abc".myAdd{"de"}  //I hope to get "abcde", I don't know whether the lambda {"de"} is correct.

但代码 A 错误,我该如何解决?

代码 A

fun String.myAdd(predicate: (String) -> String): String {
        val sb = StringBuilder(this)
        sb.append(predicate)
        return sb.toString()
}

【问题讨论】:

    标签: android kotlin


    【解决方案1】:

    如果你觉得幸运的话:

    infix fun String.myAdd(transform: (String) -> String) = this + transform(this)
    

    所以你可以打电话:

    "abc" myAdd { "de" }
    

    或者跳过中缀:

    fun String.myAdd(transform: (String) -> String) = this + transform(this)
    

    并通过以下方式调用它:

    "abc".myAdd { "de" }
    

    两者都会导致:

    "abcde"
    

    请注意,两种解决方案都允许在添加之前将当前字符串传递给给定的转换函数。如果您一开始不想要这个,而是想要一个供应商,那么您可能想要使用以下内容:

    fun String.myAdd(supplier: () -> String) = this + supplier()
    

    还是一样的结果

    【讨论】:

    • 谢谢,你的代码fun String.myAdd(transform: (String) -> String) = this + transform(this)中有两个'this',它们指向不同的对象,对吧?
    • 没有。在这种情况下,它们都是相同的。所以使用这个例子,两次都是"abc"。如果你不想这样,你应该使用供应商的底层版本。
    • 第一个this指向"abc",第二个this指向"de""abc".myAdd { "de" },对吧?
    • 没有。 this 都包含值 "abc"transform(this) 中的第二个 this 实际上意味着 transform("abc") 然后只返回值 "de" 因为转换函数对传入值没有任何作用,即 { "de" } .如果是 { "$it de" },你会得到:abcabc de 结果
    • 谢谢!如果两个this指向同一个对象,则代码fun String.myAdd(transform: (String) -> String) = this + transform(this)很难理解
    【解决方案2】:

    如果我正确理解您想将 lambda 的结果附加到原始字符串,您应该这样做:

    fun String.myAdd(predicate: (String) -> String): String {
        val sb = StringBuilder(this)
        sb.append(predicate(this))
        return sb.toString()
    }
    

    另外,predicate 是一个非常令人困惑的名称,它可能应该是其他名称,例如 transform

    【讨论】:

    • 谢谢,您的代码中有两个“this”,它们指向不同的对象,对吧?
    • 使用 StringBuilder 只是为了追加一个字符串一次是完全没用的,这是个坏例子
    【解决方案3】:
    fun String.add(append: () -> String) = this + append()
    

    用法:

    val str = "hello".add {
        "world"
    }
    

    【讨论】:

      【解决方案4】:

      扩展函数的最简单版本可以是:

      fun String.myAdd(append: (String) -> String): String {
          return this + append(this)
      }
      

      要调用你的函数,你应该写:

      println("Hello, world!".myAdd { 
          "XD"
      })
      

      它会打印Hello, world!XD

      您的代码不起作用,因为您没有传递给sb.append String,而是String -> String 类型的对象。如果你想调用这个函数,只需在它后面写(argument)(或使用方法invoke(args)),然后你的append(根据我上面的代码)将被调用并简单地返回String。

      实际上,另请参阅作为高阶函数的参数(在我的例子中称为append),您传递this 对象(在我的例子中是字符串Hello)。

      println("Hello".myAdd {
          it.reversed()
      }
      

      它会打印HelloolleH

      【讨论】:

      • 谢谢,您的代码中有两个“this”,它们指向不同的对象,对吧?为什么return this + append(it) 错了?
      • 我希望编写一个接受字符串参数并产生与结果相同的字符串的 lambda。我该如何编写 lambda? {"XD"} 正确吗?
      • append 需要将String作为参数。你可以传递任何字符串(我以为你想传递你调用函数的参数对象),所以这就是我写“this”的原因(因为它的扩展函数this 指的是接收者)。您不能在扩展函数中使用 it 关键字,因为它没有被声明。 it 关键字是单参数 lambda 的特殊名称。
      • Lambda { "XD" } 是正确的。 In 可以是(Any) -> String 或只是() -> String。这个 lambda 只在调用时返回 String(lambdas 总是返回其中的最后一条语句)。
      【解决方案5】:

      你不需要传递一个函数,你只需传递一个简单的String

      fun String.myAdd(predicate: String): String {
              val sb = StringBuilder(this)
              sb.append(predicate)
              return sb.toString()
      }
      

      但是,我认为在这里创建Stringbuilder 没有意义。 但如果只是一个教程,那也没关系。

      更新 1

      如果你需要 lambda,它会是这样的:

      fun String.myAdd(predicate: () -> String): String {
          val sb = StringBuilder(this)
          sb.append(predicate.invoke())
          return sb.toString()
      }
      

      更新 2

      我希望编写一个接受字符串参数并产生与结果相同的字符串的 lambda。如何编写 lambda?

      fun main(args: Array<String>) {
          val cc = myAdd({ it + "de" })
          System.out.println(cc)
      }
      
      fun myAdd(predicate: (String) -> String): String {
          return predicate.invoke("abc")
      }
      

      【讨论】:

      • 谢谢!为了写一个关于lambda的练习代码,所以我需要写那个
      • 好的,那你就不需要参数了。使用predicate.invoke()@HelloCW 查看更新
      • 谢谢!希望能传参数fun mySring(aa:String):String{ return "Prefix"+aa }
      • 但是在你的代码中predicate: () -&gt; String) 没有参数
      • 它不需要参数,因为{"de"} 不使用参数。试试 `` val cc = "abc".myAdd { "de" } System.out.println(cc)
      猜你喜欢
      • 2018-09-25
      • 1970-01-01
      • 1970-01-01
      • 1970-01-01
      • 1970-01-01
      • 2014-03-06
      • 1970-01-01
      • 2019-01-02
      • 2022-12-19
      相关资源
      最近更新 更多