Вы не можете monkey patch , который изменяет объекты, которые уже существуют. Однако вы можете написать неявное преобразование , которое в большинстве случаев действует одинаково (и, возможно, безопаснее).
Прежде всего, если написано unless
, вам не нужно, чтобы он был методом каждого класса. Просто вставьте его в какой-нибудь объект и импортируйте.
object Utility {
def unless(condition: => Boolean)(body: => Unit):Unit = if(!condition) body
}
import Utility._
Но иногда вы хотите хотите, чтобы он действовал как метод в классе. Например, я часто пишу
option.map(x => f(x)).getOrElse(default)
который можно было бы записать более компактно в виде сгиба:
option.fold(default)(x => f(x))
за исключением того, что Option
не имеет сгиба. Итак, я:
class OptionWrapper[A](o: Option[A]) {
def fold[Z](default: => Z)(action: A => Z) = o.map(action).getOrElse(default)
}
implicit def option_has_utility[A](o: Option[A]) = new OptionWrapper(o)
(это называется шаблоном "Прокачай мою библиотеку"). Теперь я могу использовать сложение для моего сердца, так как в любой момент, когда есть опция и я вызываю метод fold
, компилятор понимает, что метода fold
нет, и ищет любой способ преобразовать класс во что-то который имеет fold
. Существует такой метод, и новый класс делает с существующей опцией именно то, что вы хотели бы от fold
метода самого класса.