2016-01-08 2 views
0

Допустим, у меня есть база Entity чертаScala: копия случай класс от надтипу

trait Entity { 
    final val id: Long = IdGenerator.next() 
    def position: (Double, Double) 
} 

, который затем может быть расширена с некоторыми дополнительными (еще абстрактной) функциональности

sealed trait Humanoid { self: Entity => 
    def health: Double 
    def name: String 
} 

в конце концов, существуют конкретные классы случаев с функциональностью, смешанной внутри.

case class Human(
    position: (Double, Double), 
    health: Double, 
    name: String 
) 
    extends Entity with Humanoid { 

} 

Имея это, предположим, что мне нужно определить черту событий, который инкапсулирует некоторые действия от одного лица к другому

sealed trait Event[A, B] { 
    final val timestamp: Long = System.currentTimeMillis 

    def from: A 
    def to: B 

    def event: B => B 
} 

и теперь, есть случай, класс для некоторых общего случая, который работает только на гуманоидных лицах.

case class TakeDamage[A <: Entity, B <: Humanoid](damage: Int, from: A, to: B) 
    extends Event[A,B] { 
    val event = (ent: B) => { 
     //a copy of ent with some parameters changed, e.g. health 
    } 
} 

Это должно быть возможно как-то, потому что все субъекты Humanoid надтипа будут иметь необходимые поля (здоровье).

Есть ли какой-либо типичный и непреложный способ сделать это в scala, без особого кода шаблона? Или моя абстракция совершенно неправа?

ответ

1

Единственный «не уродливый» (т. Е. Не вовлекающий вонючие трюки, такие как отражение и опускание), как я могу думать, это добавить def copy(health: Double, name: String): Humanoid в черту Humanoid и реализовать его в подклассах.

Или что то же самое, что-то вроде этого:

object Humanoid { 
    def copy [T <: Humanoid](from: T, health:Double, name: String): T = from match { 
     case x: Human => x.copy (health=health, name=name) 
    } 
    } 

Там не много преимуществ второго подхода, и она менее безопасна (не существует способа предписать, что каждая реализация Humanoid будет работать с copy , вы должны полагаться на соглашение и память программиста, что почти никогда не бывает хорошим), поэтому я придерживаюсь старого, хорошего метода переопределения, если у вас есть доступ к реализациям класса.

+0

Кажется, что у бесформенного есть пример того, что я пытаюсь выполнить. Как вы оцениваете этот подход? [github link] (https://github.com/milessabin/shapeless/blob/master/examples/src/main/scala/shapeless/examples/basecopy.scala) – Alexey

+0

Я не знаю, прочитав этот код, мой мозги кипения :) Я думал, что вы ищете решение _simple_ ... Если это так, это, конечно, не так: D. – Dima

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