【问题标题】:Is it ever valid to convert an object from a base class to a subclass将对象从基类转换为子类是否有效
【发布时间】:2009-06-16 14:33:15
【问题描述】:

目前在我的应用程序中(与许多其他应用程序一样)一个名为Contact 的实体,它代表任何人。在最基本的层面上,这用于表示业务联系。但是,它也可以用来代表公司的员工。还有一些特殊类型的员工(假设有一种叫做Manager

我试图将其建模为有意义的继承关系。员工有姓名和地址,就像联系人一样,还有许多与就业相关的属性。经理也有许多经理特定的属性。

当员工晋升为经理时,困难就来了。将基类Employee转换为继承类Manager可以吗?感觉不对。我想我会在Manager 上使用专门的构造函数。

顺便说一句,NHibernate 是否支持这种行为?是否像获取员工,从员工创建经理,然后保存经理一样简单?

【问题讨论】:

    标签: nhibernate inheritance


    【解决方案1】:

    在这种情况下,我会选择组合而不是继承。如果您坚持继承,那么每次晋升或降级以及每次雇用联系人或员工离开并成为常规联系人时,您都会更改班级。

    说联系人有角色更容易。您可以将经理角色添加到联系人以提升它并删除角色以触发它。

    【讨论】:

      【解决方案2】:

      只要您的业务模式与您的领域相匹配,您就做对了。

      但是,在我看来,你应该有类似的东西:

      Manager Promote(Employee employee)
      {
         var manager = new Manager();
         //promote your employee to a manager here
         return manager;
      }
      

      在某种工作流程中。

      关于 NHibernate,听起来您正在将您的 ORM 逻辑与您的业务领域混合在一起。将员工提升为经理是一种业务领域结构,因此属于您的业务模型。然而,NHibernate 如何将您的员工和经理映射到您的数据库与您的业务模型无关,除了如何映射它们。不过,这绝对与如何将员工提升为经理无关。

      【讨论】:

      • NHibernate 的问题只是想知道 NHibernate 是否会在将对象作为基类型检索时抱怨将其保存为子类。
      【解决方案3】:

      我个人会拥有一个包含所有基本内容和角色列表的基类。
      每个角色都有自己的属性和功能。
      优点有两个:

      • 向某人授予或接受某个角色很容易
      • 它将允许您的人员担任多个角色,而无需创建“组合类”

      如果您使用单一继承,那么使用继承很快就会为您提供诸如“ManagerProgrammer”、“ProgrammerStockManager”、“ProgrammerSupport”之类的类

      【讨论】:

        【解决方案4】:

        是的,它是有效的。关于实施,您可以使用:

        • Manager 上的静态方法:public static Manager Promote(Employee employee) { ... }
        • Manager 上的专用构造函数
        • 工厂或服务类

        我认为这些方法中的任何一种都是一个很好的解决方案。我个人喜欢专门的构造函数解决方案,因为它很好地代表了现实世界:您正在从现有 Employee 创建一个新的 Manager。

        【讨论】:

        • 不要忘记 Employee Demote(经理经理)和 Employee Hire(联系人)和 Manager HireAsManager(联系人)。
        【解决方案5】:

        生日,

        如果您发现必须将派生类从一种类型转换为另一种派生类型,那么这就是初始设计存在问题的味道。

        我的直觉是你错误地表示了一个 Manager 对象。

        回到基础并从 OO 术语中思考,您的基类 (Contact) 包含 Employee 和 Manager 对象的公共元素。任何派生对象都只是基类的特化。

        在这种情况下,经理不是员工的实例吗?

        Manager 和 Employee 类都应该有一个 reportsTo 数据成员,它也是 Employee 类型。

        目前我能看到的唯一区别是 Manager 对象现在有一个 Employee 对象的集合,这些对象是它们自己的 directReports。这可能应该实现为指向 Employee 对象容器的指针。

        我想不出任何需要将 Employee 对象与 Manager 对象分开的行为专业化。

        嗯,也许可以创建包含联系人详细信息的基类 Person。

        编辑:对不起,从你的评论我想我不够清楚。我所描述的不会导致两个单独的类都直接从您的 Contact 类派生,因此您必须在运行时将 Employee 的实例更改为 Manager,这是您最初的问题。

        也就是说,我认为您不应该有两个派生类,一个 Employee 和一个 Manager,直接从您的 Contact 类继承。

        这两种情况不都是受雇于公司的人员类型吗?为什么要区分经理和员工?员工成为经理后是否不再是员工?

        拥有两个派生类,一个 Manager 和一个 Employee,恕我直言,这是完全错误的。您是否尝试过根据“isa”和“has a”关系来分解事物。那么你就可以看到你的基本结构是错误的了。

        说员工“isa”联系人是没有意义的。员工“isa”个人和个人“拥有”一组联系方式的可能性更大。

        也许将 Manager 类派生为 Employee 的特化?员工“isa”人。经理“isa”员工,其中“isa”人。

        HTH

        干杯,

        【讨论】:

        • 很抱歉,这根本没有帮助。你说我不正确地代表经理,然后继续准确描述我的提议。
        • 对不起。你还在描述我已经拥有的东西。从 Contact -> Employee -> Manager 继承。人和联系人之间的语义差异是不相关的。问题是给定了这个继承,是否可以将员工转换为员工(经理)的子类。
        【解决方案6】:

        Contact 是 Employee 的一个属性。 Worker(你的Employee)是一个角色,Manager是一个角色。 Worker 和 Manager 仍然是 Employee,但有 Roles。 Role 是 IS IN 关系,Employee 是 AM A 关系,Contact 是 HAS A 关系。 员工有一个联系人(1-1 关系)每位员工一个联系人(如果他们有两部手机等,则为 1-M,但我离题了) Employee IS IN Role(M-M 关系) 许多员工 许多角色 员工是 A(M-1 关系)- 许多员工,所有员工类型。

        所以你正在改变角色。

        【讨论】:

          猜你喜欢
          • 1970-01-01
          • 1970-01-01
          • 1970-01-01
          • 1970-01-01
          • 2013-09-03
          • 1970-01-01
          • 2022-09-29
          • 1970-01-01
          • 1970-01-01
          相关资源
          最近更新 更多