В 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]
неявное преобразование
- так как я создаю новый объект, я могу кэшировать значения там или вычислять лучшее представление; но я должен избегать этого, так как это может произойти несколько раз, и явное преобразование, вероятно, будет вызвано только один раз?
Что я ожидаю от ответа
Представьте один (или более) вариант использования (-ов), в котором разница между обеими концепциями имеет значение и объясняет, почему я бы предпочел один из них. Также объяснение сущности двух понятий и их отношение друг к другу было бы неплохо даже без примера.