2015-05-14 1 views
1

В моем прогрессе в обучении Scala я пытаюсь реализовать простой DSL с обратных вызововScala: магазин вызов по имени переменной в качестве поля классов

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

я создаю новый объект, передать его в функцию обратного вызова для хранения. Мой демо-каркасные пожары onClick метода, который должен вызвать хранимые один

Он работает с () => Unit, но мой DSL выглядит некрасиво:

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

Конечно, я мог бы сделать onClick абстрактные и осуществлять анонимный класс позже

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

Но я хочу играть с некоторыми DSL и такие

вопросов:

  • Как хранить f в _click_cb?
  • Как создать начальную «пустую» функцию для _click_cb?
  • И, может быть, есть еще более scala-путь для достижения этого? (Без анонимных классов)
+0

Я предполагаю, что 'private val: => Unit' должен фактически быть' private val _click_cb: => Unit' (_click_cb отсутствует). Но даже так, это не может быть вал, верно? Вы устанавливаете его в click(), поэтому он должен быть var. – AmigoNico

+0

Кроме того, имена click и onClick кажутся обратными: onClick должен быть тем, который вы используете, чтобы сказать, что должно произойти, когда происходит клик, и щелчок должен быть тем, который вы используете при щелчке, нет? – AmigoNico

ответ

2

уродливее версия только чтобы показать, что ленивый вал может удерживать значением параметра имя без его оценки:

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() 
} 

очистителя и более функциональной реализации:

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

    def onClick(): Unit =() 
}