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