How can I programmatically make methods chainable?

前端 未结 4 1597
栀梦
栀梦 2021-02-09 05:30

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 = {
             


        
4条回答
  •  耶瑟儿~
    2021-02-09 06:15

    Leaving aside the question of how wise this is in the first place, it's pretty easy to implement in a type-safe and boilerplate-free way with Shapeless:

    import shapeless._
    
    trait ChainableUtils {
      def makeChainable[F, Args <: HList](f: F)(implicit
        in: FnHListerAux[F, Args => Unit],
        out: FnUnHLister[Args => this.type]
      ) = out((a: Args) => { in(f)(a); this })
    }
    

    And then:

    scala> class MyClass extends ChainableUtils {
         |   def func1 = makeChainable((i: Int) => println("Doing stuff."))
         |   def func2 = makeChainable((a: Any, b: Any) => 
         |     println("Doing other stuff."))
         | }
    defined class MyClass
    
    scala> val myInstance = new MyClass
    myInstance: MyClass = MyClass@6c86b570
    
    scala> myInstance.func1(1).func2('a, "a").func1(42)
    Doing stuff.
    Doing other stuff.
    Doing stuff.
    res0: myInstance.type = MyClass@6c86b570
    

    This will work for any FunctionN.

提交回复
热议问题