2013-05-20 4 views
1

ситуация:случай класса и наследование: как предложить различное поведение

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 

При использовании обычных классов, простой признак наследования и сам-типа в фактической величине можно определить его и динамику поставок.

К сожалению, я должен переопределить поля в признаке. Я думаю, это справедливый компромисс. Было бы интересно узнать, знает ли кто-нибудь другой подход.

Благодаря

ответ

2

Не уверены, что о вашем случае использования, но вам нужно определить класс A как это, если вы хотите, чтобы сделать его работу:

abstract case class A(x: Double, y: Double) extends Operation 

Но я не думаю, что это очень идиоматический подход для использования классов случаев. Они в основном используются в качестве контейнеров данных и обычно не содержат никакого поведения. (Может быть, вы можете сказать, более подробную информацию о вещи, которые вы хотите достичь с этим)

+0

благодаря @tenshi, если я сделать корпус класс аннотацию, я не смогу создать его экземпляр. То, что я пытаюсь сделать, - это классический объектно-ориентированный родительский класс с методом, определенным для каждого подкласса. Однако этот метод может быть повторно использован другой иерархией, поэтому я хотел бы сделать его базовым признаком. Я просто не могу найти, как его извлечь. – fracca

+0

@fracca вы все еще можете создать экземпляр, смешивая в некоторой операции: 'new A (1.0, 2.0) с OperationMinus'. Но в вашем примере метод 'something' является абстрактным, поэтому вам нужно либо определить его, либо сделать весь класс абстрактным. Или вы можете напрямую расширять 'OperationMinus' или' OperationPlus' в классе 'A' и не объявлять его абстрактным. – tenshi

+0

абстрактный класс case эффективно позволяет сохранить преимущества класса case и смешения в поведении. Однако, поскольку что-то операция определяется на основе A, мне нужно переопределить поля x и y. – fracca

2

Во-первых, вы должны иметь:

trait OperationPlus extends Operation 
trait OperationMinus extends Operation 

Во-вторых, вы не можете определить A в случае класса, так что автоматически определяет apply метод на сопутствующем объекте, где вызывается new A (с аргументами). Этот вызов терпит неудачу из-за неправильного типа пользователя (ошибка, которую вы видите).

Удалить case. Если вам необходимо соответствие шаблона, определить экстрактор самостоятельно (реализации unapply):

class A(val x: Double, val y: Double) { this: Operation => } 

object A { 
    def unapply(v: A) = Some((v.x, v.y)) 
} 

 Смежные вопросы

  • Нет связанных вопросов^_^