ситуация:случай класса и наследование: как предложить различное поведение
trait Operation {
def something: Double
}
trait OperationPlus { this: A =>
override def something: Double = x + y
}
trait OperationMinus { this: A =>
override def something: Double = x - y
}
case class A(x: Double, y: Double) { this: Operation =>
}
val a = new A(1.0, 2.0) with OperationPlus
println(a.something)
ошибка:
class A cannot be instantiated because it does not conform to its self-type A with Operation
Кроме того, я не могу создать экземпляр А.
Я попробовал несколько различных подходов, но никто не обеспечил то, что я ищу. Я не хочу использовать наследование класса case, или отказаться от классов case, и в идеале типы trait/self/что-то еще должны делать трюк. Есть идеи?
Обновление предпочтительного решения
trait Operation { this: A =>
def something: Double
}
trait OperationPlus extends Operation { this: A =>
override def something: Double = x + y
}
trait OperationMinus extends Operation { this: A =>
override def something: Double = x - y
}
abstract case class A(val x: Double, val y: Double) extends Operation
val a = new A(1.0, 2.0) with OperationPlus
println(a.something)
val b = new A(1.0, 2.0) with OperationMinus
println(b.something)
Возможное решение 1:
trait Operation {
def x:Double
def y:Double
def something: Double
}
trait OperationPlus extends Operation {
override def something: Double = x + y
}
trait OperationMinus extends Operation {
override def something: Double = x - y
}
abstract case class A(val x: Double, val y: Double) extends Operation
При использовании обычных классов, простой признак наследования и сам-типа в фактической величине можно определить его и динамику поставок.
К сожалению, я должен переопределить поля в признаке. Я думаю, это справедливый компромисс. Было бы интересно узнать, знает ли кто-нибудь другой подход.
Благодаря
благодаря @tenshi, если я сделать корпус класс аннотацию, я не смогу создать его экземпляр. То, что я пытаюсь сделать, - это классический объектно-ориентированный родительский класс с методом, определенным для каждого подкласса. Однако этот метод может быть повторно использован другой иерархией, поэтому я хотел бы сделать его базовым признаком. Я просто не могу найти, как его извлечь. – fracca
@fracca вы все еще можете создать экземпляр, смешивая в некоторой операции: 'new A (1.0, 2.0) с OperationMinus'. Но в вашем примере метод 'something' является абстрактным, поэтому вам нужно либо определить его, либо сделать весь класс абстрактным. Или вы можете напрямую расширять 'OperationMinus' или' OperationPlus' в классе 'A' и не объявлять его абстрактным. – tenshi
абстрактный класс case эффективно позволяет сохранить преимущества класса case и смешения в поведении. Однако, поскольку что-то операция определяется на основе A, мне нужно переопределить поля x и y. – fracca