Можно ли использовать черты для построения системы игровых компонентов в Scala? - PullRequest
4 голосов
/ 07 апреля 2011

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

Например.У вас есть GameObject.Сам по себе GameObject ничего не делает, но то, что вы в него смешиваете, придает ему дополнительные свойства.Компоненты могут быть HealthComponent (имеет здоровье), PhysicsComponent (имитирует физику), ClickableComponent (можно щелкнуть).

Мне нравится идея использования признаков, потому что все свойства и методы добавляются в исходный объект, и яможно сделать player.getHP вместо player.getHealthComponent.getHP.С другой стороны, я считаю странными названия и семантику использования черт.trait HealthComponent extends GameObject - это не имеет смысла.HealthComponent принадлежит GameObject, он не соответствует - это отношение , подразумеваемое extend.Правильно ли я считаю, что черты обычно рассматриваются как специализированные версии родительского класса?Если так, то как бы я назвал что-то вроде вышеуказанного объекта?

Ответы [ 3 ]

4 голосов
/ 07 апреля 2011

В дополнение к @ ответу Морица также возможно составлять связанное поведение без наследования реализации от супертипа:

trait HasFoo { def foo: Unit }

class GameObject extends HasFoo {
   def foo = {}
}

trait Health extends HasFoo { 
   self: GameObject =>

   abstract override def foo = {
      println("health foo")
      super.foo
   }
}

trait Dog extends HasFoo { 
   self: GameObject =>

   abstract override def foo = {
      println("dog foo")
      super.foo
   }
}

scala> val g = new GameObject with Health with Dog
g: GameObject with Health with Dog = $anon$1@33b7b32c

scala> g.foo
dog foo
health foo
3 голосов
/ 07 апреля 2011

"trait HealthComponent расширяет GameObject - this doesn't make sense. A HealthComponent` принадлежит GameObject" - вам нужно selftype и построение в соответствии с тортом :

Итак, у вас есть

trait HealthComponent {
   me: GameObject =>

   def inspect { me.querySomeGameObjectProperty }
}

val x = new GameObject with HealthComponent with ...

"Правильно ли я считаю, что черты обычно рассматриваются как специализированные версии их родительского класса?" - Я бы так не сказал. Если вы выберете подход «снизу вверх», подобный описанному выше, вы будете думать не столько о том, чтобы черты были подтипами некоторых родителей, а наоборот (более крупные компоненты состоят из черт и специализируются по ним)

3 голосов
/ 07 апреля 2011

Если вы хотите ограничить типы, в которые может быть смешана ваша черта, вы можете выразить зависимость как собственный тип:

trait Health { self: GameObject =>
 // ...
}

class Player extends GameObject with Movement with Health

Таким образом, ваша черта не расширяется GameObject, но может быть толькоиспользуется как миксин для подтипов GameObject.

См. также Понимание торта Scala и связанной статьи.

...