Как я могу добавить новые методы к объекту библиотеки?

У меня есть класс из библиотеки (в частности, 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и пусть они сочиняют.

Другие вопросы по тегам