В настоящее время у меня есть код со структурой, подобной следующей:
object Example {
val doctor : Healer[Cancer] = new Doctor
val parent : Healer[Cold] = new Parent
val generic: Healer[Sickness] = new Generic
def cure(sickness: Sickness): Boolean = sickness match {
case cancer: Cancer => doctor.cure(cancer)
case cold : Cold => parent.cure(cold)
case other => generic.cure(other)
}
}
class Sickness
class Cancer extends Sickness
class Cold extends Sickness
// other sicknesses
abstract class Healer[A <: Sickness] {
def cure(sickness: A): Boolean
}
abstract class Treatment[A <: Sickness] {
def cure(sickness: A): Boolean
}
class Doctor[A <: Cancer] extends Healer[A] {
val treatments: List[Treatments[A]] = List(
new Chemotherapy,
new Surgery,
new HopesAndPrayers
)
def cure(sickness: A): Boolean = {
// ... choose a treatment
treatment.cure(sickness)
}
}
class Chemotherapy[A <: Cancer] extends Treatment[A] {
def cure(cancer: A): Boolean = {
// without generics, needs a check for Cancer
}
}
// other Healers (e.g. Parent, Generic) and other Treatments (e.g. BedRest, HealthyFood)
Это как дженерики правильно / нормально используются?Должен ли / мог ли я выделить его на Treatment
и / или Healer
?Если да, то как?
Чтобы объяснить более подробно, это началось без обобщений, но когда я начал создавать подклассы Treatments
, такие как Chemotherapy
, я закончил с cure(sickness: Sickness)
методами, которые содержат sickness match { case cancer: Cancer => ... }
.Казалось, что если бы у меня был класс SomeSpecificTreatment
, который имел дело только с SomeSpecificSickness
, было бы разумно иметь метод cure(sickness: SomeSpecificSickness)
, а не cure(sickness: Sickness)
.
Поэтому я добавил дженерики в Treatment
, и они, следовательно, пробились до Example
.Когда это происходит, я обычно чувствую, что делаю что-то не так.Я особенно подозрительно отношусь к Example#cure
.С большим количеством подклассов Sickness
список дел может стать довольно длинным, и я инстинктивно чувствую, что это можно сделать по-другому и лучше (не так ли?).Я подумал об использовании Map
для выполнения чего-то вроде healers.getOrElse(sickness.getClass, generic)
, но он не будет вести себя так же, как типы сопоставления с образцом, и у меня все равно обычно возникают проблемы с вложенными обобщениями.
Поскольку это может произойти: У меня нет контроля над Sickness
или его подклассами, и я не могу изменить подпись Example#cure