Как я могу добавить новые методы к объекту библиотеки?
У меня есть класс из библиотеки (в частности, com.twitter.finagle.mdns.MDNSResolver
). Я хотел бы расширить класс (я хочу, чтобы он возвращал Future[Set], а не Try[Group]).
Я знаю, конечно, что я мог бы подкласс этого и добавить свой метод там. Тем не менее, я стараюсь изучать Scala, и это похоже на возможность попробовать что-то новое.
Причина, по которой я думаю, что это возможно, - это поведение JavaConverters
, Следующий код:
class Test {
var lst:Buffer[Nothing] = (new java.util.ArrayList()).asScala
}
не компилируется, потому что нет asScala
метод на Java ArrayList
, Но если я импортирую некоторые новые определения:
class Test {
import collection.JavaConverters._
var lst:Buffer[Nothing] = (new java.util.ArrayList()).asScala
}
то вдруг есть asScala
метод. Так это выглядит как ArrayList
класс расширяется прозрачно.
Понимаю ли я поведение JavaConverters
правильно? Могу ли я (и должен ли я) продублировать эту методологию?
3 ответа
Scala поддерживает так называемые неявные преобразования. Посмотрите на следующее:
val x: Int = 1
val y: String = x
Второе задание не работает, потому что String
ожидается, но Int
найден. Однако, если вы добавляете следующее в область действия (просто в область, может прийти откуда угодно), это работает:
implicit def int2String(x: Int): String = "asdf"
Обратите внимание, что имя метода не имеет значения.
То, что обычно делается, называется pimp-my-library-pattern:
class BetterFoo(x: Foo) {
def coolMethod() = { ... }
}
implicit def foo2Better(x: Foo) = new BetterFoo(x)
Это позволяет вам звонить coolMethod
на Foo
, Это используется так часто, что начиная с Scala 2.10, вы можете написать:
implicit class BetterFoo(x: Foo) {
def coolMethod() = { ... }
}
который делает то же самое, но, очевидно, короче и приятнее.
Так что вы можете сделать:
implicit class MyMDNSResolver(x: com.twitter.finagle.mdns.MDNSResolver) = {
def awesomeMethod = { ... }
}
И вы сможете позвонить awesomeMethod
на любом MDNSResolver
, если MyMDNSResolver
находится в сфере.
Это достигается с помощью неявных преобразований; эта функция позволяет автоматически преобразовывать один тип в другой при вызове метода, который не распознан.
В частности, шаблон, который вы описываете, называется "обогатить мою библиотеку" после статьи, написанной Мартином Одерским в 2006 году. Это все еще хорошее введение в то, что вы хотите сделать: http://www.artima.com/weblogs/viewpost.jsp?thread=179766
Способ сделать это с неявным преобразованием. Их можно использовать для определения представлений, а их использование для обогащения существующей библиотеки называется " pimp my library".
Я не уверен, если вам нужно написать преобразование из Try[Group]
в Future[Set]
или вы можете написать один из Try
в Future
и еще один из Group
в Set
и пусть они сочиняют.