罗兰谈MATLAB的艺术

将想法转化为MATLAB

MATLAB中的子类

我很高兴Dave Foti回来讨论MATLAB中的子类化和类层次结构。Dave管理着MATLAB中负责面向对象编程特性的小组。

在计算机科学中,类代表一组具有共同定义的对象,通常包括数据、函数或行为。子类表示对象的子集,这些对象通常通过添加或专门化超类中定义的数据和/或函数来共享更特定的定义。在实践中,子类化被用于重用功能,以实现新的和更专门的目的。近年来,这种用法在很大程度上已被劝阻,因为在应用程序中重用超类(通常称为基类)而不是原始类所预期的应用程序时,倾向于引入错误。类作者隐藏了类的内部工作,以使类作为抽象表示有用。同样的细节隐藏也会阻碍程序员预测类在新角色中如何工作的能力。让我们来探索一些在MATLAB中子类化是有意义的情况,以及如何避免一些常见的编程陷阱。

内容

物理系统建模

在MATLAB中,子类化最明显的用途之一是需要一个已经分类的真实物理系统的模型。在这种情况下,构建一个与实际物理分类系统非常相似的软件模型可能是有意义的。例如,人们可以基于粒子物理学的标准模型创建对象[1].这样,分类系统已经存在,并且可以简单地在软件中表示。对于如何在软件中最好地表示一个特定目的的物理系统,仍然有设计工作要做,但是所有的类都可以由同一个人或团队在大致相同的时间构建,从而避免在忘记详细信息之后重用现有类的陷阱。下面是标准模型中基本粒子的超类:

类型ElemParticle
自旋电荷质量end %特定粒子属性的状态变量Position = [0 0 0];速度= [0 0 0];end方法函数p = ElemParticle(自旋,电荷,质量)p.Charge =电荷;p.质量=质量;结束结束

然后我们可以为费米子和玻色子创建子类:

类型费米子类型玻色子
classdef费米子< ElemParticle方法函数p =费米子(电荷,质量)p@ElemParticle(。5、电荷、质量);end end classdef玻色子< ElemParticle方法函数p =玻色子(质量)p@ElemParticle(0,0,质量);结束结束

我们可以把费米子分为轻子和夸克:

类型轻子类型夸克
classdef Lepton <费米子方法函数p = Lepton(电荷,质量)p@Fermion(电荷,质量);结束结束结束classdef夸克<费米子属性颜色结束方法函数p =夸克(电荷,质量,颜色)p@Fermion(电荷,质量);p.Color =颜色;结束结束

在上面的例子中,超类和子类被设计为一个类集合,因此不需要超类来预测未知的未来子类的需求。超类未来的任何演变都需要考虑整个系统,但它是一个有限的类列表。

抽象数据结构系统

即使没有使用在软件中有意义的现有分类模型对物理系统建模,仍然有其他示例,在这些示例中,可以大致同时设计类系统来实现某些目的,例如管理各种数据格式或分析技术。例如,我们可能需要将一些数据可视化为点。我们可能知道我们有两种数据集:一种是二维的,一种是三维的。我们设计了一个处理二维数据的类和一个增加对第三维数据支持的子类。金宝app下面是2d类的样子:

类型PointList
classdef PointList属性X Y结束方法(Sealed)函数显示(pc)图;data = getData(pc);opts = {'+', 'MarkerSize', 3};如果数字(数据)== 3 plot3(数据{:},opts{:});{:}其他情节(数据,选择{:});端端端方法(访问=保护)函数数据= getData ={个人电脑(pc)数据。X, pc.Y};结束结束

因为我们知道我们想要支持3-D数据,所以我们设计了绘图例程,使其金宝app能够处理2-D或3-D数据。这是在一开始就了解所有子类的一个优势。然后,当我们编写3d子类时:

类型PointList3D
classdef PointList3D < PointList属性Z结束方法(访问=保护)函数数据= getData ={个人电脑(pc)数据。X,电脑。Y, pc.Z};结束结束

不需要重写整个显示方法,就可以很容易地金宝app支持3d图。这里我们为l型膜的三次谐波生成一个三维点云:

L =膜(3);[X, Y] = meshgrid(1:length(L), 1:length(L));pts = PointList3D;分。Z = l (:);分。X = X(:);分。Y = Y(:);显示(分)

mixin

使用子类化的另一个好理由是父类是专门为重用而设计的。通用设计模式[2]叫做mixin模式[3].在这种模式中,类通常用于实现一个专门的功能。这个类表示所有具有此通用功能的对象,即使这些类的其他功能可能非常不同。除了使用mixin功能外,mixin类不应该期望子类。MATLAB中mixin类的一个常见示例是类matlab.mixin.CustomDisplay用于自定义MATLAB默认对象显示,同时与其他对象保持适当的一致性。下面是一个mixin的例子ElemParticle超类。为了将这个版本与前一个示例分开,我将新版本的类放在一个名为粒子

类型+粒子/ ElemParticle
自旋电荷质量end %特定粒子属性的状态变量Position = [0 0 0];速度= [0 0 0];end方法函数p = ElemParticle(自旋,电荷,质量)p.Charge =电荷;p.质量=质量;函数propgroups = getPropertyGroups(p) propgroups = matlab.mix .util. propertygroup;propgroups(1)。标题= '内在的';propgroups(1)。PropertyList = getintrincicpropertynames (p); propgroups(2).Title = 'State'; propgroups(2).PropertyList = {'Position','Velocity'}; end end methods(Access = protected) function pnames = getIntrinsicPropertyNames(~) pnames = {'Spin','Charge','Mass'}; end end end

请注意,每当为这样的超类设计功能时,重要的是为整个对象类实现功能,包括子类的所有实例。因此,显示不应该只是显示什么是共同的ElemParticle,但是应该提供子类的专门化。在本例中,我们添加了一个方法,该方法可以由子类特殊化,以提供内在属性列表。因为我们知道所有的子类,所以我们不需要担心将来的子类可能需要什么类型的属性组。我们可以看到为什么在设计超类时知道子类将被创建是很重要的,以及为什么在设计过程中已经知道子类是很有帮助的。在本例中,我们知道的子类族ElemParticle因此,我们知道他们有时需要添加新的属性,但不是一组全新的属性。我们在父类中选择适当数量的通用性,以便每个子类可以以最小的工作量专门化显示。事实上夸克是唯一需要额外代码的粒子,如下所示:

类型+粒子/夸克
夸克<粒子。费米子properties Color end methods function p = Quark(charge, mass, color) p@particle.Fermion(charge, mass); p.Color = color; end end methods(Access = protected) function pnames = getIntrinsicPropertyNames(p) pnames = [getIntrinsicPropertyNames@particle.Fermion(p), 'Color']; end end end

我们现在可以创建并显示一个电子和一个顶夸克:

E =粒子。轻子(-1, 5.11e-4)
e =轻子与性质:本征自旋:0.5电荷:-1质量:0.000511状态位置:[0 000]速度:[0 000]
T =粒子。夸克(2/3, 173.07,“红色”
t =夸克性质:本征自旋:0.5电荷:0.66667质量:173.07颜色:“红色”状态位置:[0 0 0]速度:[0 0 0]

其他模式

将类设计为无界子类的其他常见模式包括接口[4]和框架[5].接口类定义了两段代码如何相互交互,而不实际定义这些交互是如何完成的。因为MATLAB是一种动态类型语言,所以可以将函数编写到没有实际定义为类的接口。例如,MATLAB中的许多函数可以与任何实现大小subsref,subsasgn函数对数组执行重塑操作。在某些情况下,显式地定义接口可能是有用的,这样可以更容易地确定什么类型的对象将与特定函数一起工作,并且更容易在它支持的显式接口中看到类的功能。金宝app

设计注意事项

在将来设计一个用于扩展的类时,最好考虑一下子类如何限制基类的演化。需要考虑的问题有:

  • 是否清楚将来不需要向基类添加任何属性或方法?
  • 随着时间的推移,只需要更改内部实现细节,而不需要更改类的基本含义和行为,这是否清楚?

在基类中设计方法时,重要的是要考虑子类将如何重用,并在必要时调整这些方法,同时保持子类实例可以替代基类实例的原则[6].可以问的问题有:

  • 哪些方法可能需要专门化?
  • 怎样才能最好地组织基类方法,以允许子类重用尽可能多的基类实现?
  • 是否有更好的方法来确保子类的行为仍然与类的预期行为一致?

一旦一个类被表示为基类,它的基本定义就不应该改变,否则子类就会失效或产生错误的结果。新的或更改的行为和功能可能不适合所有子类。创建子类时,子类的作者不可能预料到父类的变化。这是坚持开放/封闭设计原则的原因之一[7]

防止意外子类化

考虑到子类如何扩展类的重要性,MATLAB提供了一些方法来表明类不是为子类设计的。具有Sealed属性集的类不能用作超类。如果整个类层次结构是一起设计的,但不打算使用其他子类进行扩展,那么可以使用叶类上的sealed属性和超类上的AllowedSubclasses属性对其进行密封。MathWorks有时会对广泛使用的类的类或类层次结构进行密封,以表明这些类未被设计为支持子类。金宝app

这些是关于MATLAB中子类化的一些想法,但我也想听听你们的想法。你用过MATLAB中的mixin类吗matlab.mixin.CustomDisplaymatlab.mixin.Heterogeneous?对于你想在MATLAB中看到的mixin类,你有什么建议吗?

参考文献




发布与MATLAB®R2014b

|
  • 打印
  • 发送电子邮件

评论

如欲留言,请点击在这里登录您的MathWorks帐户或创建一个新帐户。