Oop 域模型中的继承与枚举属性

Oop 域模型中的继承与枚举属性,oop,inheritance,enums,domain-driven-design,domain-model,Oop,Inheritance,Enums,Domain Driven Design,Domain Model,我在工作中讨论过“域模型中的继承使开发人员的生活复杂化”。我是一名OO程序员,所以我开始寻找这样的论点:在域模型中进行继承实际上会简化开发人员的生活,而不是到处都有开关 我想看到的是: class Animal { } class Cat : Animal { } class Dog : Animal { } 另一位同事说的是: public enum AnimalType { Unknown, Cat, Dog } public class Animal

我在工作中讨论过“域模型中的继承使开发人员的生活复杂化”。我是一名OO程序员,所以我开始寻找这样的论点:在域模型中进行继承实际上会简化开发人员的生活,而不是到处都有开关

我想看到的是:

class Animal {

}

class Cat : Animal {

}

class Dog : Animal {

}
另一位同事说的是:

public enum AnimalType {
    Unknown,
    Cat,
    Dog
}

public class Animal {

    public AnimalType Type { get; set; }

}
我如何说服他(links是欢迎的),在这种情况下,类层次结构比拥有enum属性更好


谢谢

最重要的是,OOPS意味着建模现实。遗传给你机会说猫是动物。动物不应该知道它现在是不是一只猫在叫它,然后决定它应该是喵喵叫而不是吠叫,封装在那个里被打败了。现在的代码更少,您不必像您所说的那样执行If-else

以下是我对此的理由:

仅当角色/类型永远不会更改时才使用继承。 e、 g

将继承用于以下内容:

消防员在以下情况下枚举是好的:

  • 这组值是固定的,从不改变或很少改变
  • 您希望能够表示值的并集(即组合标志)
  • 您不需要将其他状态附加到每个值。(Java没有这个限制。)
  • 如果您可以用一个数字来解决您的问题,那么枚举可能是一个很好的选择,而且类型更安全。如果您需要比上述更大的灵活性,那么枚举可能不是正确的答案。使用多态类,您可以:

  • 静态地确保处理所有特定于类型的行为。例如,如果您需要所有动物都能
    Bark()
    ,那么使用抽象
    Bark()
    方法创建
    Animal
    类将让编译器为您检查每个子类是否实现了它。如果您使用一个枚举和一个大的
    开关
    ,它不能确保您已经处理了所有情况

  • 您可以添加新案例(示例中的动物类型)。这可以跨源文件,甚至跨包边界完成。对于枚举,一旦声明它,它就被冻结。开放式扩展是OOP的主要优势之一

  • 需要注意的是,你同事的例子与你的例子并不直接相反。如果他希望动物的类型是一个公开属性(这对某些事情很有用),您仍然可以不使用枚举,使用:


    这为您提供了枚举的便利:您可以执行
    AnimalType.Cat
    ,然后可以获得动物的类型。但它也给了您类的灵活性:您可以向
    AnimalType
    添加字段来存储每种类型的额外数据,添加虚拟方法,等等。更重要的是,您可以通过创建
    AnimalType

    的新实例来定义新的动物类型。我敦促您重新考虑:在一个(根据上面的评论),猫的行为和狗没有什么不同,所以没有多态性。动物的类型实际上只是一种属性。很难看出继承为您带来了什么。

    两种解决方案都是正确的。 你应该看看哪些技术更适合你的问题

    如果您的程序使用很少的不同对象,并且没有添加新类,那么最好使用枚举


    但是,如果您的程序使用了许多不同的对象(不同的类),并且可能会添加新的类,那么在将来,最好尝试继承方式。

    拥有一个枚举就像为所有这些人开派对一样。
    打开/关闭的原则是为吸盘


    它确实邀请您检查动物是否属于某种类型,然后为每种类型应用自定义逻辑。这可能会产生可怕的代码,这使得在系统上继续构建变得非常困难。

    这是针对内存中的对象模型还是ORM?我不认为动物的例子很有用,因为它没有解决你在进行真正的OO设计时所面临的许多常见问题。@Marcelo:同意。具体来说,行为角度是什么?狗吠,猫喵喵,使用同事的实现,这些行为在C#中很难实现(例如)。它在F#等函数式语言中仍然很有用,在F#中,有区别的联合是提供多态性的一种非常强大的手段。@Marcelo和@sfinine:它是ORM和业务层的一个贫乏的域模型。在我看来,域模型类可以具有对其他类没有意义的属性。我们设法在EF 4中具有“每个层次结构表继承”(Table per Hierarchy Inheritation),这样查询就不会那么难看了。是的,每个层次结构表使数据库更加光滑,但是,为了使其工作,您必须编写多少xml?这可能不仅仅是switchstatement,只是说。我们避免了先用数据库编写xml,而不是手动创建其余的映射实体并将它们映射到wright表。我会竭尽全力使用任何“用多态性替换条件”类型的重构,避免完全打开对象类型或枚举值。谢谢。。“猫的行为和狗没有什么不同,所以没有多态性。”这似乎是一个很好的理由。
    freddy.Roles.Add(new Employement( employmentDate, jobTitle ));
    
    freddy.CurrentEmployment = new Employement( employmentDate, jobTitle );
    
    public abstract class AnimalType {
        public static AnimalType Unknown { get; private set; }
        public static AnimalType Cat { get; private set; }
        public static AnimalType Dog { get; private set; }
    
        static AnimalType() {
            Unknown = new AnimalType("Unknown");
            Cat = new AnimalType("Cat");
            Dog = new AnimalType("Dog");
        }
    }
    
    public class Animal {
        public AnimalType Type { get; set; }
    }