如何以编程方式使方法可链接? [英] How can I programmatically make methods chainable?

查看:46
本文介绍了如何以编程方式使方法可链接?的处理方法,对大家解决问题具有一定的参考价值,需要的朋友们下面随着小编来一起学习吧!

问题描述

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

Let's say I have a class and I want to make its methods chainable, I could do something like this:

class MyClass {

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

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

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

While that would achieve the functionality I'm looking for, it's not very elegant in my opinion. Is there a better way of doing this?

假设有可能,我希望能够执行以下操作,但我不确定如何处理 makeChainable 函数.

Assuming it's possible, I'd like to be able to do something like the following, but I'm not sure how to approach the makeChainable function.

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

}

推荐答案

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

The first option is the most efficient one, the other one introduces overhead by wrapping code into function object. But it's certainly possible to create such a wrapper. Let's define

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,它说我们函数的结果是它们定义的类的类型.所以现在当我们把它混合到我们的类中时

Notice this.type, it says the result of our functions is the type of the class they're defined in. So now when we mix it into our class

class MyClass extends Chainable {
  val methodTwo =
    mkChain((x: Any, y: String) => println("Doing something " + y));
}

methodTwo 的结果将是 MyClass.

更新:还有另一种选择,使用隐式转换:

Update: There is another option, to use implicit conversions:

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") 之类的东西.

Calling chain converts anything to this.type. However it only works inside the class, you can't call something like new MyClass2.methodOne(3).chain.methodTwo("x") outside.

更新:另一种解决方案,基于从Unitthis的隐式转换:

Update: Yet another solution, based on implicit conversion from Unit to 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);
}

这篇关于如何以编程方式使方法可链接?的文章就介绍到这了,希望我们推荐的答案对大家有所帮助,也希望大家多多支持IT屋!

查看全文
登录 关闭
扫码关注1秒登录
发送“验证码”获取 | 15天全站免登陆