建模(和映射)具有两个多态性程度的类层次结构
本文关键字:程度 多态性 层次结构 两个 映射 建模 | 更新日期: 2023-09-27 18:25:55
在父/子层次结构中,我遇到了两个多态性级别,一个在另一个中。
我认为最好用一个简单的例子来解释这一点:
class Group
{
public IList<Person> People { get; set; }
}
class SpecialGroup : Group
{
public IList<SpecialPerson> People { get; set; }
}
class Person {}
class SpecialPerson : Person {}
因此,一个Group有一个Person对象列表,而一个专门的Group(SpecialGroup)有一个Person(SpecialPerson)对象的专门列表。
这是编译的,但我收到一条警告,说我应该在SpecialGroup.Peoples上使用"new"关键字,因为它隐藏了Group.Peopes属性。
我理解这意味着什么,但也许我不完全理解如何在C#中正确地建模这样的东西。对如何以更好的方式建模有什么想法吗?
还有,你知道NHibernate会怎么玩吗?我不确定使用"new"关键字是否会减少它,因为Group.People属性可能已经映射为不同的类型。有没有更好的方法来建模,以与NH兼容的方式?
好吧,我想了一种使用泛型建模的方法:
abstract class AbstractGroup<PersonType>
where PersonType : Person
{
public IList<PersonType> People { get; set; }
}
class Group : AbstractGroup<Person>
{}
class SpecialGroup : AbstractGroup<SpecialPerson>
{}
class Person {}
class SpecialPerson : Person {}
我想这是我想要的吗?现在Person可以与SpecialPerson共享特征,但只有SpecialPerson可以添加到SpecialGroup中。AbstractGroup基类型可以为任何组的共同特征建模。
现在的问题是,如果我试图绘制这个地图,NH会爆炸吗?
记录在案,似乎有些人已经成功地将query-over与泛型类一起使用了——对于HQL查询(我的用例),这是不受支持的。
我想到的另一种方法是简单地隐藏属性的父级实现,例如,在子类中为重写属性使用"new"关键字-下面的线程讨论了为什么这也不起作用:
NHibernate:每个子类的表映射和新的关键字
到目前为止的结论:运行时检查和异常,正如下面@empi所建议的。
这种情况也称为"并行"或"双重"继承。
通常,在一个层次结构中有一个特定的类,它与另一个相关。
虽然不需要,但最好每个类都有一个"泛型"或"抽象"类,必须重写,但已经有了依赖性的概念。
这种情况在图形界面控件中非常常用,可能适用于其他情况。
在这种特殊情况下,通常最好只显示第一级:
............................................................
....+----------------+................+----------------+....
....| <<Abstract>> |..<<contains>>..| <<Abstract>> |....
....| AbstractGroup +<>--------------+ AbstractPerson |....
....| |................| |....
....+----------------+................+----------------+....
............................................................
但是,您可以对多个级别进行建模,这是不推荐的:
............................................................
....+----------------+................+----------------+....
....| <<Abstract>> |..<<contains>>..| <<Abstract>> |....
....| AbstractGroup +<>--------------+ AbstractPerson |....
....| |................| |....
....+-------+--------+................+--------+-------+....
............|..................................|............
............|..................................|............
............^..................................^............
............|..................................|............
............|..................................|............
....+-------+--------+................+--------+-------+....
....| <<Concrete>> |..<<contains>>..| <<Concrete>> |....
....| Group +<>--------------+ Person |....
....| |................| |....
....+----------------+................+----------------+....
............|..................................|............
............|..................................|............
............^..................................^............
............|..................................|............
............|..................................|............
....+-------+--------+................+--------+-------+....
....| <<Concrete>> |..<<contains>>..| <<Concrete>> |....
....| SchoolGroup +<>--------------+ Student |....
....| |................| |....
....+----------------+................+----------------+....
............................................................
您提到NHibernate,您的类是否表示要存储的数据?
一些类似的问题:
避免并行继承层次结构
并行继承层次重构
如何避免GUI控件和域对象之间的并行继承层次结构
C++中接口类与实现类的并行继承
干杯。
如果您想强制执行SpecialGroup
只包含SpecialPerson
的规则,那么您可以在不隐藏People属性的情况下以程序方式执行。我想你有一些方法AddPerson
。如果有人试图添加不是SpecialPerson
的条目,您可以在SpecialGroup
中覆盖它并抛出异常。如果您想要获得SpecialPerson
的列表,那么您可以添加方法IEnumerable<SpecialPerson> GetSpecialPeople()
并将Person
强制转换为SpecialPerson
(由于您在AddPerson
方法中检查类型,因此它将始终是有效的强制转换)。通过这样做,你不必跟踪People的财产,NHibernate会很好地工作。