среда, 15 мая 2013 г.

Неявные преобразования (Implicit conversions)

Привет всем!

Не один раз нам приходилось писать что-то наподобии:

val button = new JButton

button.addActionListener(new ActionListener {
  def actionPerformed(e: ActionEvent) {
    println("A lot of boiler-plate code.")
  }
})

Код выше -- не Скале, но код на Java немногим отличается (да еще и более многословен).

Все вроде нормально, но он содержит так называемый boiler plate code.
Т.е. к смысловому значению "подмешивается"  "обвязка", код, который нужен языку, а не программисту.

Смысл тут в строке println(...) и в том что мы "вешаем" обработчик на кнопку. Создание анонимного внутреннего класса (который имплементирует интерфейс ActionListener) и описание метода actionPerformed(...) это то, что приходится писать, а не то что хочется.

Использую возможность Скалы неявного преобразования типов можно свести вышеописанное к простому виду:

button.addActionListener((e: ActionEvent) => {
    println("Much better")
})

Напишите функцию в scope кода выше:

/**
* Implicit conversion function:
* from function: (ActionEvent => Any)
*
* Note: You can choose any name you want for this function
*/
implicit def ActionListenerToFunction(fn: (ActionEvent => Any)) = new ActionListener {
  def actionPerformed(e: ActionEvent) {
    fn(e)
  }
}

Эту функцию также можно подключать во всех классах где она может быть нужной (что и делается в очень многих местах стандартной библиотеки классов Scala).

Как все это работает:

Если в коде встречается функция, которая принимает ActionEvent, а возвращает тип Any, то происходит замена такого кода кодом: 

    new ActionListener {
      def actionPerformed(e: ActionEvent) {
        fn(e)
      }
    }  
т.е.неявная функция-преобразователь сделает за нас работу по имплементированию  интерфейса и вызовет fn() с параметром "е". А сама fn(...)  это --
    (e: ActionEvent) => {
       println("Much better")
    })

Техника неявного преобразования широко используется в языке Скала и является одной из возможностей, которой нет в Java.

Главное -- это использовать ее в меру, поскольку подключения массы таких функций из разных мест может серьезно осложнить чтение кода.

Комментариев нет:

Отправить комментарий