Внедрить методы в существующие классы - PullRequest
3 голосов
/ 18 ноября 2010

Я хочу найти способ определить новый метод в некотором существующем классе в Scala.

Например, я думаю, что у метода asInstanceOf[T] слишком длинное имя, я хочу заменить его на as[T].

Прямой подход может быть:

class WrappedAny(val a: Any) {
  def as[T] = a.asInstanceOf[T]
}

implicit def wrappingAny(a: Any): WrappedAny = new WrappedAny(a)

Есть ли более естественный способ с меньшим количеством кода?

Также, когда я пытаюсь это сделать, происходит странная вещь:

scala> class A

defined class A

scala> implicit def toA(x: Any): A = x

toA: (x: Any)A

scala> toA(1)

И консоль зависла. Кажется, что toA(Any) не должен проходить этап проверки типа, и не может, когда это неявно. И помещение всего кода во внешний исходный код может вызвать ту же проблему. Как это случилось? Это ошибка компилятора (версия 2.8.0)?

Ответы [ 3 ]

8 голосов
/ 18 ноября 2010

Технически нет ничего плохого в вашем подходе к сутенерству Any, хотя я думаю, что в целом он опрометчив.Точно так же есть причина, по которой asInstanceOf и isInstanceOf так многословно названы;это отговорить вас от их использования!Почти наверняка есть лучший, статически безопасный для типов способ сделать все, что вы пытаетесь сделать.

Что касается примера, который приводит к зависанию вашей консоли: объявленный тип toA равен Any => A, но все жевы определили его результат как x, который имеет тип Any, а не A.Как это возможно скомпилировать?Хорошо, помните, что когда происходит явная ошибка типа, компилятор ищет все доступные неявные преобразования для решения проблемы.В этом случае ему требуется неявное преобразование Any => A ... и оно находит: toA!Таким образом, причина проверки типа toA заключается в том, что компилятор неявно переопределяет его как:

implicit def toA(x: Any): A = toA(x)

... что, конечно, приводит к бесконечной рекурсии при попытке его использования.

3 голосов
/ 18 ноября 2010

Во втором примере вы передаете Any функции, которая должна возвращать A.Однако он никогда не возвращает A, а тот же Any, который вы передали. Затем компилятор пытается применить неявное преобразование, которое, в свою очередь, не возвращает A, но Any и т. Д.

Если вы определите toA как неявное, вы получите:

scala> def toA(x: Any): A = x           
<console>:6: error: type mismatch;
 found   : Any
 required: A
       def toA(x: Any): A = x
                            ^
1 голос
/ 19 ноября 2010

Как оказалось, это уже обсуждалось в списках Scala.Шаблон pimp my class действительно немного многословен для того, что он делает, и, возможно, может быть способ очистить синтаксис без введения новых ключевых слов.

Немного о новых ключевых словах - это одна из целей Scalaсостоит в том, чтобы сделать язык масштабируемым с помощью библиотек, вместо того, чтобы превращать язык в гигантское одеяло идей, отвечающих чьим-либо критериям «достаточно полезных для добавления в язык», и в то же время сделать другие идеи невозможными, потому что они не былисчитается полезным и / или достаточно распространенным.

Во всяком случае, до сих пор ничего не произошло, и я не слышал, что в этой цели ведется какая-либо работа.Вы можете присоединиться к сообществу через его списки рассылки и внести свой вклад в его развитие.

Добро пожаловать на сайт PullRequest, где вы можете задавать вопросы и получать ответы от других членов сообщества.
...