scala - 如何以编程方式使方法可链接?

标签 scala

假设我有一个类,我想让它的方法可链接,我可以这样做:

class MyClass {

  def methodOne(arg1: Any): MyClass = {
    println("doing stuff")
    this
  }

  def methodTwo(arg1: Any, arg2: Any): MyClass = {
    println("doing other stuff")
    this
  }
}

虽然这将实现我正在寻找的功能,但在我看来它并不是很优雅。有没有更好的方法来做到这一点?

假设有可能,我希望能够执行以下操作,但我不确定如何处理 makeChainable功能。
class MyClass {

  val methodOne: Any => MyClass = 
    makeChainable((arg1: Any) => println("doing stuff"))

  val methodTwo: (Any, Any) => MyClass = 
    makeChainable((arg1: Any, arg2: Any) => println("doing other stuff"))

}

最佳答案

第一个选项是最有效的,另一个选项通过将代码包装到函数对象中来引入开销。但是创建这样的包装器当然是可能的。让我们定义

trait Chainable {
  final def mkChain(f: () => Any): () => this.type =
    () => { f(); this; }
  final def mkChain[A](f: (A) => Any): (A) => this.type =
    (x: A) => { f(x); this; }
  final def mkChain[A,B](f: (A,B) => Any): (A,B) => this.type =
    (x: A, y: B) => { f(x, y); this; }
  // etc. for other arities
}

通知this.type ,它说我们的函数的结果是它们定义的类的类型。所以现在当我们将它混合到我们的类中时
class MyClass extends Chainable {
  val methodTwo =
    mkChain((x: Any, y: String) => println("Doing something " + y));
}
methodTwo 的结果将是 MyClass .

更新:还有另一种选择,使用隐式转换:
trait ToChain {
  implicit class AsThis(val _underlying: Any) {
    def chain: ToChain.this.type = ToChain.this
  }
}

class MyClass2 extends ToChain {
  def methodOne(arg1: Any): Unit =
    println("Doing something")
  def methodTwo(arg1: String): Unit =
    println("Doing something else " + arg1)

  methodOne(3).chain.methodTwo("x");
}

调用 chain将任何内容转换为 this.type .但是它只在类内部有效,你不能调用类似 new MyClass2.methodOne(3).chain.methodTwo("x") 的东西。外部。

更新:另一个解决方案,基于来自 Unit 的隐式转换至 this :
import scala.language.implicitConversions

class Chain[A](val x: A) {
  implicit def unitToThis(unit: Unit): A = x;
}
implicit def unchain[A](c: Chain[A]): A = c.x;

// Usage:

val r: MyClass = new Chain(new MyClass) {
  x.methodOne(1).methodTwo(2,3);
}

关于scala - 如何以编程方式使方法可链接?,我们在Stack Overflow上找到一个类似的问题: https://stackoverflow.com/questions/17692536/

相关文章:

regex - Scala中的IDEA 13正则表达式检查器

scala - 使 JVM scala 库在 Scala.js 中可用

scala - 如何在 Spark Notebook 中导入库

scala - 如何在 Scala 中构建合适的命名空间?

scala - 在 Scala 中将 List[Try[A]] 转换为 List[A]

scala - 对一系列类型的抽象

Scala:如何设置在抽象父类(super class)构造函数中定义的实例字段?

java - Scala 抽象类翻译成 Java

java - 使用 Stream DSL 在 Kafka Streams 中指定每个流/表时间戳提取器

java - 如何将类放入 Scala 中 JJS ScriptEngine 的范围中