假设我有一个类,我想让它的方法可链接,我可以这样做:
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/