我对UML中的泛化、聚合和抽象类有点困惑。
通过概括,我可以理解这是一个“是”的关系。学生是一个人——老师是一个人。所以 Person 将是超类,而学生和老师都是子类。
通过聚合,这就是我的理解:与组合相比,这是一种“更软”的关系。一个例子可能是:你可以有没有手指的手(聚合),但你不能有没有手的手指(组合)。
然后我完全迷失在抽象类上。抽象类的特点是什么?如果可能的话,我想要一个例子。
但我在正确的轨道上吗?这就是我对这些术语的理解。
我对UML中的泛化、聚合和抽象类有点困惑。
通过概括,我可以理解这是一个“是”的关系。学生是一个人——老师是一个人。所以 Person 将是超类,而学生和老师都是子类。
通过聚合,这就是我的理解:与组合相比,这是一种“更软”的关系。一个例子可能是:你可以有没有手指的手(聚合),但你不能有没有手的手指(组合)。
然后我完全迷失在抽象类上。抽象类的特点是什么?如果可能的话,我想要一个例子。
但我在正确的轨道上吗?这就是我对这些术语的理解。
你了解泛化。
关联可以是聚合或组合(或两者都不是)。这是 Tom Pender 曾经使用的一个很好的例子。假设你有一个 Car 类。那个 Car 类“有”一个方向盘、座椅、两个车轴、四个轮子等等。如果您在制造商环境中创建汽车,那么所有这些之间的关系将是组合:汽车所有部件(在您的制造商处)的寿命与汽车的寿命相关。从制造商的角度来看,当您将汽车交付给经销商时,汽车及其所有部件的使用寿命就结束了。
现在,假设您是垃圾场的所有者。在这种情况下,汽车仍然“拥有”所有这些零件,但它们有自己的生命周期:您可以从汽车上出售零件,如果需要,甚至可以将它们制成其他汽车的一部分。汽车与这些零件之间的关系是聚合,因为零件的寿命与汽车本身的寿命无关。
因此,您可以看到同一辆车实际上可以根据上下文以两种不同的方式进行建模。
至于抽象类:抽象类只是一个定义方法和/或属性的类,同时要求它们只能在子类中实现。用接口解释为什么是最容易的。接口是抽象类,附加条件是没有一个方法或属性可以直接在类中实现(您可能会说它是如何定义子类的定义)。这就是它们有用的地方。
假设我想定义一个 Animal 类。动物做什么?嗯,他们动了。他们咬人。(当然,它们也做其他事情,但让我们坚持使用移动和咬咬。)如果我创建一个动物界面,我会说“这就是动物所做的事情。如果你想成为动物,你也必须这样做这些东西。但是,我不会告诉你如何去做。所以,我创建了一个 iAnimal 接口,它有两个方法,Move 和 Bite。作为一个接口,我不提供任何类型的实现,只是空程序。
现在,假设我有两只动物,一只跳蚤和一只 TRex。显然,跳蚤和特雷克斯在它们的移动方式或咬合方式上没有任何共同点,但它们两者都有。我会让 Flea 和 TRex 继承或“实现”接口,提供适合动物类型的 Move 和 Bite 实现。
这样做的好处是我的 flea 和 trex 的客户不必知道他们正在处理的是哪一个。他们可以创建一个 iAnimal,根据需要注入 Flea 或 TRex 的实例,并安全地调用 iAnimal 的 Move 和/或 Bite 方法,而不必担心它们是否受支持。(这就是我们所说的“多态性”)。
所以,接口实现是泛化的一种形式(更准确地说是专业化,相反),你可能已经猜到了。
从这里开始,“抽象类”就是任何定义了必须继承才能实现的方法或属性的类。因此,正如我所说,接口是抽象类。然而,在一般用法中,抽象类是指一个不是接口的类,即具有一些具体方法或属性的类。大多数编程语言都遵循这个定义。