MATLAB 和其他面向对象语言的比较
与 C++ 和 Java 代码的一些差异
在某些重要的方面,MATLAB® 编程语言与 C++ 或 Java® 等其他面向对象的语言有所不同。
公共属性
与 C++ 或 Java 语言中的字段不同,您可以使用 MATLAB 属性定义独立于数据存储实现的公共接口。您可以提供对属性的公共访问,因为您可以定义 set 和 get 访问方法,这些方法会在分配或查询属性值时自动执行。例如,以下语句:
myobj.Material = 'plastic';
将 char
向量 plastic
赋给 myobj
的 Material
属性。在进行实际赋值之前,myobj
执行名为 set.Material
的方法(假设 myobj
的类定义了该方法),该方法可以执行任何必要的操作。有关属性访问方法的详细信息,请参阅属性 get 和 set 方法。
您还可以通过设置特性来控制对属性的访问,包括公共、受保护和私有三种访问权限。有关属性特性的完整列表,请参阅属性特性。
没有隐式参数
在某些语言中,方法的对象参数始终是隐式的。在 MATLAB 中,方法所作用的对象参数是显式的。
调度
在 MATLAB 类中,方法调度不像在 C++ 和 Java 代码中那样基于方法签名。当参量列表包含同等优先级的对象时,MATLAB 使用最左边的对象选择要调用的方法。
但是,如果某个参量的类优先于其他参量的类,MATLAB 将调度优先参量的方法,而不管它位于参量列表中的什么位置。
有关详细信息,请参阅 Class Precedence。
调用超类方法
在 C++ 中,您可以使用作用域运算符调用超类方法:
superclass::method
在 Java 代码中,您使用的是:
superclass.method
等效的 MATLAB 操作是
。method@superclass
其他差异
在 MATLAB 类中,没有 C++ 模板或 Java 泛型的等效项。但是,MATLAB 不强调类型,因此您可以编写能够处理不同类型数据的函数和类。
MATLAB 类不支持对同一函数名称使用不同的签名来重载函数。
对象修改
MATLAB 类可以定义公共属性,要修改这些属性,您可以在类的给定实例中为这些属性显式赋值。但是,只有从 handle
类派生的类才会表现出引用行为。如果在值类(即并非从 handle
派生的类)的实例中修改属性值,则只会在修改所处的上下文中更改值。
后续章节将更详细地说明此行为。
传递给函数的对象
MATLAB 按值传递所有变量。当您将对象传递给函数时,MATLAB 会将值从调用方复制到被调函数的参数变量中。
但是,MATLAB 支持两种在复制时有不同行为的类:
句柄类 - 句柄类实例变量引用一个对象。句柄类实例变量的副本引用与原始变量相同的对象。如果函数修改作为输入参量传递的句柄对象,则此修改会影响这一同时由原始句柄和复制句柄引用的对象。
值类 - 值类实例中的属性数据独立于该实例副本中的属性数据(尽管值类属性可能包含句柄)。函数可以修改作为输入参量传递的值对象,但这种修改不会影响原始对象。
有关这两种类的行为和用法的详细信息,请参阅句柄类和值类的比较。
传递值对象. 当您将值对象传递给函数时,函数会创建参量变量的本地副本。该函数只能修改副本。如果要修改原始对象,请返回修改后的对象,并将其赋给原始变量名称。例如,假设有值类 SimpleClass
:
classdef SimpleClass properties Color end methods function obj = SimpleClass(c) if nargin > 0 obj.Color = c; end end end end
创建 SimpleClass
的一个实例,将值 red
赋给其 Color
属性:
obj = SimpleClass('red');
将对象传递给函数 g
,该函数将 blue
赋给 Color
属性:
function y = g(x) x.Color = 'blue'; y = x; end
y = g(obj);
函数 g
修改输入对象的副本并返回该副本,但不更改原始对象。
y.Color
ans = blue
obj.Color
ans = red
如果函数 g
未返回值,则对象 Color
属性的修改只会发生在函数工作区内的 obj
的副本上。当函数执行结束时,此副本将超出作用域。
覆盖原始变量实际上会将其替换为新对象:
obj = g(obj);
传递句柄对象. 当您传递函数的句柄时,函数会创建句柄变量的副本,就像传递值对象一样。但是,由于句柄对象的副本引用与原始句柄相同的对象,因此函数可以修改对象,而不必返回修改后的对象。
例如,假设您修改 SimpleClass
类定义,使其成为 handle
类的派生类:
classdef SimpleHandleClass < handle properties Color end methods function obj = SimpleHandleClass(c) if nargin > 0 obj.Color = c; end end end end
创建 SimpleHandleClass
的一个实例,将值 red
赋给其 Color
属性:
obj = SimpleHandleClass('red');
将对象传递给函数 g
,该函数将 blue
赋给 Color
属性:
y = g(obj);
函数 g
会设置这一由返回的句柄和原始句柄同时引用的对象的 Color
属性:
y.Color
ans = blue
obj.Color
ans = blue
变量 y
和 obj
引用同一个对象:
y.Color = 'yellow';
obj.Color
ans = yellow
函数 g
修改了输入参量引用的对象 (obj
),并在 y
中返回该对象的句柄。
MATLAB 按值传递句柄. 句柄变量是对一个对象的引用。MATLAB 按值传递该引用。
句柄的行为与 C++ 中的引用不同。如果您将对象句柄传递给函数,而该函数将另一对象赋给该句柄变量,则调用方中的变量不受影响。例如,假设您定义函数 g2
:
function y = g2(x) x = SimpleHandleClass('green'); y = x; end
将句柄对象传递给 g2
:
obj = SimpleHandleClass('red');
y = g2(obj);
y.Color
ans = green
obj.Color
ans = red
该函数覆盖作为参量传入的句柄,但不覆盖句柄引用的对象。原始句柄 obj
仍然引用原始对象。
静态属性
在 MATLAB 中,类可以定义常量属性,但不能定义 C++ 等其他语言中所说的“静态”属性。您不能将常量属性更改为类定义中指定的初始值以外的值。
一直以来,MATLAB 规定变量始终优先于函数和类的名称。赋值语句会在没有变量的情况下引入变量。
以下形式的表达式
A.B = C
引入新变量 A
,它是一个 struct
,其中包含值为 C
的字段 B
。如果 A.B = C
可以表示类 A
的静态属性,则类 A
将优先于变量 A
。
此行为与 MATLAB 的早期版本明显不兼容。例如,如果在 MATLAB 路径上引入名为 A
的类,则可能会更改 .m
代码文件中类似 A.B = C
的赋值语句的含义。
在其他语言中,类很少使用静态数据,除非作为类中的私有数据或公共常量。在 MATLAB 中,您可以像在 Java 中使用 public
、final
和 static
字段一样使用常量属性。要使用 MATLAB 中某个类的内部数据,请使用私有方法、受保护的方法或该类私有的局部函数来创建持久变量。
避免在 MATLAB 中使用静态数据。如果类有静态数据,在多个应用程序中使用同一个类会导致应用程序之间发生冲突。在其他一些语言中,冲突不是什么大问题。这些语言将应用程序编译成在不同进程中运行的可执行文件。每个进程都有自己的类静态数据副本。MATLAB 经常在同一进程和环境中运行许多不同应用程序,每个类只有一个副本。
有关在 MATLAB 中定义和使用静态数据的方法,请参阅静态数据。
常见的面向对象编程方式
下表提供一些章节的链接,这些章节讨论其他面向对象语言常用的面向对象编程方式。
编程方式 | 在 MATLAB 中如何运用 |
---|---|
运算符重载 | 运算符重载 |
多重继承 | Subclassing Multiple Classes |
子类化 | 设计子类构造函数 |
析构函数 | 句柄类析构函数 |
限定数据成员的作用域 | 属性特性 |
命名空间(限定类的作用域) | 包命名空间 |
具名常量 | 请参阅定义具有常量值的类属性和Named Values |
枚举 | 定义枚举类 |
静态方法 | 静态方法 |
静态属性 | 不支持。请参阅 有关可变静态数据,请参阅静态数据 |
构造函数 | 类构造函数方法 |
复制构造函数 | 没有直接等效项 |
引用/引用类 | 句柄类和值类的比较 |
抽象类/接口 | 抽象类和类成员 |
垃圾回收 | 对象生命周期 |
实例属性 | 动态属性 - 向实例添加属性 |
导入类 | 导入类 |
事件和侦听程序 | 事件和侦听程序概念 |