В Scala мы можем использовать как минимум два метода для модификации существующих или новых типов. Предположим, мы хотим выразить, что что-то можно определить количественно, используя Int
. Мы можем определить следующую черту.
Неявное преобразование
trait Quantifiable{ def quantify: Int }
И тогда мы можем использовать неявные преобразования для количественной оценки, например. Строки и списки.
implicit def string2quant(s: String) = new Quantifiable{
def quantify = s.size
}
implicit def list2quantifiable[A](l: List[A]) = new Quantifiable{
val quantify = l.size
}
После их импорта мы можем вызвать метод quantify
для строк и списков. Обратите внимание, что в количественном списке сохраняется его длина, поэтому он избегает дорогостоящего обхода списка при последующих вызовах quantify
.
Типы занятий
Альтернативой является определение «свидетеля» Quantified[A]
, который утверждает, что некоторый тип A
может быть определен количественно.
trait Quantified[A] { def quantify(a: A): Int }
Затем мы предоставляем экземпляры этого класса типов для String
и List
где-то.
implicit val stringQuantifiable = new Quantified[String] {
def quantify(s: String) = s.size
}
И если мы затем напишем метод, который должен количественно определить его аргументы, мы напишем:
def sumQuantities[A](as: List[A])(implicit ev: Quantified[A]) =
as.map(ev.quantify).sum
Или используя синтаксис с привязкой к контексту:
def sumQuantities[A: Quantified](as: List[A]) =
as.map(implicitly[Quantified[A]].quantify).sum
Но когда использовать какой метод?
Теперь встает вопрос. Как я могу выбрать между этими двумя понятиями?
То, что я заметил до сих пор.
тип занятий
- классы типов допускают красивый синтаксис с привязкой к контексту
- с классами типов Я не создаю новый объект-оболочку при каждом использовании
- синтаксис, связанный с контекстом, больше не работает, если класс типа имеет несколько параметров типа; представьте себе, что я хочу дать количественную оценку не только целым числам, но и значениям общего типа
T
. Я хотел бы создать класс типа Quantified[A,T]
неявное преобразование
- так как я создаю новый объект, я могу кэшировать значения там или вычислять лучшее представление; но стоит ли этого избегать, поскольку это может произойти несколько раз, и явное преобразование может быть вызвано только один раз?
Что я ожидаю от ответа
Представьте один (или несколько) вариантов использования, в которых имеет значение различие между этими двумя понятиями, и объясните, почему я предпочел бы одно другому. Также было бы неплохо объяснить суть этих двух понятий и их связь друг с другом, даже без примера.