歧视的工会和继承

jdo*_*oig 4 inheritance f# discriminated-union

我正在为我的F#项目创建一个场景图:

root
->player_bob
-->torch
->enemy_1
-->extravagant_hat
-->enemies_cat_jess 
--->fleas
--->fur_ball
->loot
Run Code Online (Sandbox Code Playgroud)

等等,等等.

每个项目都需要保存一组游戏对象来代表它的孩子.

例如,enemy1的列表包含猫和帽子,猫列表包含跳蚤和毛球

所以我计划让它们全部继承自一个包含描述对象子集合的集合的类.

现在回答我的问题: 我应该将子对象向下转换为GameObject,并将它们存储在"GameObject"基类的列表中,或者创建一个有区别的联合,例如

type SceneObject = 
        |Character of Character //e.g player, enemy, cat
        |Item of Item //e.g hat, torch, furball
Run Code Online (Sandbox Code Playgroud)

并将对象存储为"SceneObjects"列表,以避免任何问题/开销,以及向上转换它们等.同时允许我描述在碰撞检测中不渲染和/或不使用对象的特殊情况,例如:声音发射器,陷阱触发器等

歧视的联合+继承组合是我最初的想法; 尽管如此,由于我是FP的新手,我认为向专业人士询问最佳,实用,接近这一点的方式是明智的.

谢谢,

JD

Dar*_*rio 10

您可以递归地使用区分联合.

type SceneObject = 
    | Character of <characterData> * (SceneObject list) 
    | Item      of <itemData>      * (SceneObject list)
Run Code Online (Sandbox Code Playgroud)

并像这样使用它

let root = [Character("Bob", [Item("Torch", []); ...]); ...]
Run Code Online (Sandbox Code Playgroud)


Tom*_*cek 8

Dario建议的替代方法是为游戏中的实际对象声明一个单独的类型(例如项目和字符),并将其包装在另一个添加子对象列表的对象中.这看起来像这样:

type SceneObject =
  | Character of <characterData>
  | Item of <itemData>

type ObjectWithChildren = 
  { Object : SceneObject
    Children : ObjectWithChildren list }
Run Code Online (Sandbox Code Playgroud)

这两个选项都是正确的功能设计,但我更喜欢这个版本,因为它使某些类型的处理更容易.例如,如果要遍历游戏树中的所有对象,可以编写如下内容:

let rec traverse tree = 
  // Do something with tree.Object
  for child in tree.Children do traverse child
Run Code Online (Sandbox Code Playgroud)

在此版本中,您根本不需要进行模式匹配SceneObject,因此您不需要包含所有情况(例如ItemCharacter).