简体   繁体   中英

Scala: store call-by-name variable as class field

In my progress in Scala learning I try to implement a simple DSL with callbacks

object Button {...} // apply 
class Button(val name: String) {
    private val: => Unit; // doesn't work

    def click(f: => Unit) = {
        _click_cb = f
        this
    }

    def onClick() = this._click_cb()
}

Button("Click me!") click {println("Clicked!")}

I create a new object, pass it a callback to store. My demo framework fires onClick method, that should call the stored one

It works with () => Unit but my DSL looks ugly:

Button("Click me!") click (() => println("Clicked!"))

Sure, I could do onClick abstract and implement an anonymous class later

new Button("Click me!") {def onClick = println("Clicked!")}

But I want to play with some DSL and such

The questions are:

  • How do I store f in _click_cb ?
  • How do I provide initial "empty" function for _click_cb ?
  • And maybe there's a more scala-way to achieve this? (without anonymous classes)

An uglier version just to show that lazy val can hold the by name parameter value without evaluating it:

case class Button(val name: String) {
  def clickCallback(): Unit = ()

  def click(f: => Unit) = {
    lazy val notEvaluated = f
    new Button(name) { override def clickCallback() = notEvaluated }
  }

  def onClick(): Unit = clickCallback()
}

A cleaner and more functional implementation:

class Button(val name: String) {
  def click(f: => Unit) = new Button(name) { override def onClick() = f }

  def onClick(): Unit = ()
}

The technical post webpages of this site follow the CC BY-SA 4.0 protocol. If you need to reprint, please indicate the site URL or the original address.Any question please contact:yoyou2525@163.com.

 
粤ICP备18138465号  © 2020-2024 STACKOOM.COM