我以前听说过多重继承的陷阱,我知道.Net开发人员反对将其包含在内。
话虽如此,举一个简单的例子,比如"游戏公司"。游戏公司可以是:
- 软件开发人员,如PlatinumGames
- 出版商,例如Agetec
- 同时是开发商和发行商,如暴雪娱乐
- 仅限游戏硬件制造商(手头没有完全是制造商的公司的例子)
- 以上所有,即任天堂
如果我必须在.Net中对此进行建模,我该如何处理"是"关系存在的事实,并且一家公司可以同时是其中的多个?想象一下,我已经建模了一个:
Game
类,具有List<Developer>
和Publisher
作为属性- 具有
Manufacturer
属性的Console
类
在理想的场景中,这应该是尽可能类型安全的,并且易于过滤和导航到每个类和从每个类导航(就像某种完全连接的实体框架映射)。
我也以同样的方式思考了一些事情,对此我可能知道"正确"的答案。
如果我将FatPerson
和TallPerson
作为基类,并希望"绕过"多重继承限制,该怎么办?因为很有可能同时拥有一个又胖又高的人。在这种情况下,如果有一个Person
有两个属性,Weight
和Height
,完全消除基类,可能会更干净。这只是一个重写我以前基于对象类型的任何过滤的问题,以考虑这些新的属性。
对于每一个多重继承案例,是否都有本质上等效的东西?对于我提出的这个特殊案例,该怎么办?
更新:
我读过这个答案,它被标记为我的副本(在发布这个之前),但我在这里有点不同意。我认为这与将SQL优化问题标记为其他所有SQL优化问题的重复相同。最后,每个案例都是不同的案例,需要不同的方法/答案。我认为这适用于这里,因为我问了一个非常固定的案例,就像另一个答案一样。
此场景是基于角色的软件工程的一个很好的例子,是当前研究的主题。这是因为这个问题没有唯一的解决方案。有几种方法,但都有缺点。
接口是设计类型关系的好方法。如果您制作例如Developer
和Publisher
接口,则可能存在同时使用这两种接口的公司。然而,您不能从接口继承代码,并且通常会得到大量重复的代码。
更进一步,您提出了mixin继承。这基本上是用扩展方法增强的接口实现。看看这个例子:
class Company { }
interface Publisher { }
public static class PublisherMixin
{
public static void Publish(this Publisher p)
{
//do something
}
}
class CompanyThatIsAPublisher : Company, Publisher { }
然后你可以做
var c = new CompanyThatIsAPublisher():
c.Publish();
您可以对多个mixin执行此操作。您甚至可以在弱引用字典的帮助下为mixin提供状态。
避免代码重复的另一种方法是委派。您仍然有接口层次结构,但为开发人员角色、发布者角色等创建对象。然后,公司只将方法调用转发给这些子对象。然而,这会导致客体精神分裂症。子对象并不真正属于可能造成问题的主对象。但是,您可以轻松地交换它们。
在C#中,您还可以使用DynamicObject。这样,您就可以动态地注册角色,并将方法调用动态地重新路由到适当的对象。因此,一家开发公司最终可以成为一家出版商,而不必失去自己的身份。这种方法也有对象精神分裂症的问题。