Решение с неявным преобразованием
Кен предположил, что прокси может помочь нам в этом случае.Здесь мы пытаемся добавить черту к экземпляру после его создания.Это «исправление обезьян» может быть полезно, если кто-то еще написал класс (и метод apply()
), и вы не можете получить доступ к источнику.В этом случае вы можете добавить прокси / оболочку поверх экземпляра путем неявного преобразования (ручное преобразование не требуется):
Используя пример Foo
, мы можем сделать это следующим образом:
class Foo
object Foo { def apply() = new Foo }
trait Baz { def usefulMethod(s: String) = "I am really useful, "+ s }
// ---- Proxy/Wrapper ----
class FooWithBazProxy extends Foo with Baz
// --- Implicit conversion ---
implicit def foo2FooWithBazProxy(foo: Foo): FooWithBazProxy = new FooWithBazProxy
// --- Dummy testcode ---
val foo = Foo()
println(foo.usefulMethod("not!"))
Выходы:
I am really useful, not!
Этот пример мне не нравится:
Baz
не использует Foo
в любомпуть.Трудно понять причину, по которой мы хотели бы присоединить usefulMethod()
к Foo
.
Так что я сделал новый пример, в котором черта, на которую мы «запрягаем обезьяну»экземпляр фактически использует экземпляр:
// --------- Predefined types -----------
trait Race {
def getName: String
}
class Avatar(val name: String) extends Race{
override def getName = name
}
object Avatar{
def apply() = new Avatar("Xerxes")
}
// ---------- Your new trait -----------
trait Elf extends Race {
def whoAmI = "I am "+ getName + ", the Elf. "
}
// ---- Proxy/Wrapper ----
class AvatarElfProxy(override val name: String) extends Avatar(name) with Elf
// ---- Implicit conversion ----
implicit def avatar2AvatarElfProxy(Avatar: Avatar): AvatarElfProxy = new AvatarElfProxy(Avatar.name)
// --- Dummy testcode ---
val xerxes= Avatar()
println(xerxes.whoAmI)
Prints:
I am Xerxes, the Elf.
В этом примере добавленная черта Elf
использует метод getName
экземпляра, который он расширяет.
Буду признателен, если вы обнаружите какие-либо ошибки, я не очень хорошо понимаю (пока).