如何避免在具有继承的不可变数据模型中出现代码重复?
给定一个类层次结构,例如:
Entity { id, name, position }
Combatant : Entity { health, strength }
Avatar : Combatant { connection }
都是不可变的。
要在实体上实现“移动”,我可以返回具有不同位置的新实体。
Entity Move(p) { return new Entity(id, name, p); }
但是,如果我对阿凡达调用“移动”,我将得到一个实体,而不是阿凡达。所以我必须在所有不可变类上实现“移动”。有没有办法避免这种情况,或者更好的解决方案?
Given a class hierarchy such as:
Entity { id, name, position }
Combatant : Entity { health, strength }
Avatar : Combatant { connection }
Which are all immutable.
To implement 'move' on an entity I can return a new entity with a different position.
Entity Move(p) { return new Entity(id, name, p); }
However if I call 'move' on an Avatar, I will get an Entity, not an Avatar. So I have to implement 'move' on all immutable classes. Is there a way to avoid this, or a better solution?
如果你对这篇内容有疑问,欢迎到本站社区发帖提问 参与讨论,获取更多帮助,或者扫码二维码加入 Web 技术交流群。
绑定邮箱获取回复消息
由于您还没有绑定你的真实邮箱,如果其他用户或者作者回复了您的评论,将不能在第一时间通知您!
发布评论
评论(3)
您可以使用泛型来解决此问题,为了简单起见,我假设所有属性都有受保护的设置器:
为了允许当前类型保持原样,您可以为每个具体类型对泛型基进行简单的继承:
有关深度克隆的示例,您可以点击此链接,尽管我应该指出,如果性能重要,这样会更好要求每个继承类重写此方法并将自己的属性添加到克隆过程中。
you can resolve this with generics, i am assuming for the sake of simplicity that there are protected setters for all the properties:
To allow the current types to remain as they are you can do a simple inheritance of the generic base for each concrete type:
For a examples for deep cloning you can follow this link although i should point out that if performance is important, it would be better to require each inheriting class to override this method and add their own properties to the cloning process.
您需要将运动逻辑与模型分离。 (始终坚持 SOLID 原则)。其余的与 NightDweller 的帖子类似,
您的代码可能如下所示:
或者
然后为您的每个类实现此接口。
根据运动的算法,您也可以考虑使用装饰器模式。
You need to decouple the logic of movement from your model. (always stick to SOLID principles). The rest is similiar to NightDweller's post
your code may look like this:
or
then implement this interface for ech of your classes.
depending on the algorithm of movement, you may also consider using decorator pattern.
在尝试在一些业余爱好项目中广泛使用不可变类型后,我得出的结论是,在 C# 中,除了以下特殊情况之外,它们需要付出相当大的努力:类型是从
object 继承的结构体或密封类
,并且没有集合字段。不幸的是,在所有其他情况下,我认为不可变类型带来的麻烦远远超过它们在 C# 中的价值,尽管我更愿意更多地使用它们。
你确定你希望这个类的层次结构是不可变的吗?
这已经很棘手了,当你添加一个作为集合的属性/字段时,你的困难就会突破天际。例如,除非您非常小心地执行此操作,否则 .Move 将必须创建集合的深层副本。但即使您对 .Move 足够小心,替换集合中单个元素的单个属性也肯定需要复制整个集合。 ETC...
Having tried to use immutable types extensively in some hobby projects, I came to the conclusion that in C#, they are quite a bit of effort except in the following special case: the type is a struct or a sealed class inheriting from
object
, and has no fields that are collections.In all other cases I think immutable types are far more trouble than they are worth in C#, unfortunately, even though I'd rather like to use them more.
Are you sure you want this hierarchy of classes to be immutable?
It's already tricky, and the moment you add a property/field that is a collection your difficulties will shoot through the roof. For example, unless you do it very carefully, .Move will have to create deep copies of collections. But even if you are careful enough with .Move, replacing a single property of a single element in a collection will definitely require the whole collection to be copied. Etc...