Main Content

MATLAB 和其他面向对象语言的比较

与 C++ 和 Java 代码的一些差异

在某些重要的方面,MATLAB® 编程语言与 C++ 或 Java® 等其他面向对象的语言有所不同。

公共属性

与 C++ 或 Java 语言中的字段不同,您可以使用 MATLAB 属性定义独立于数据存储实现的公共接口。您可以提供对属性的公共访问,因为您可以定义 set 和 get 访问方法,这些方法会在分配或查询属性值时自动执行。例如,以下语句:

myobj.Material = 'plastic';

char 向量 plastic 赋给 myobjMaterial 属性。在进行实际赋值之前,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

变量 yobj 引用同一个对象:

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 中使用 publicfinalstatic 字段一样使用常量属性。要使用 MATLAB 中某个类的内部数据,请使用私有方法、受保护的方法或该类私有的局部函数来创建持久变量。

避免在 MATLAB 中使用静态数据。如果类有静态数据,在多个应用程序中使用同一个类会导致应用程序之间发生冲突。在其他一些语言中,冲突不是什么大问题。这些语言将应用程序编译成在不同进程中运行的可执行文件。每个进程都有自己的类静态数据副本。MATLAB 经常在同一进程和环境中运行许多不同应用程序,每个类只有一个副本。

有关在 MATLAB 中定义和使用静态数据的方法,请参阅静态数据

常见的面向对象编程方式

下表提供一些章节的链接,这些章节讨论其他面向对象语言常用的面向对象编程方式。

编程方式在 MATLAB 中如何运用
运算符重载运算符重载
多重继承Subclassing Multiple Classes
子类化设计子类构造函数
析构函数句柄类析构函数
限定数据成员的作用域属性特性
命名空间(限定类的作用域)包命名空间
具名常量请参阅定义具有常量值的类属性Named Values
枚举定义枚举类
静态方法静态方法
静态属性

不支持。请参阅 persistent 变量。如需 Java 中 staticfinal 或 C++ 中 staticconst 属性的等效项,请使用 Constant 属性。请参阅定义具有常量值的类属性

有关可变静态数据,请参阅静态数据

构造函数类构造函数方法
复制构造函数没有直接等效项
引用/引用类句柄类和值类的比较
抽象类/接口抽象类和类成员
垃圾回收对象生命周期
实例属性动态属性 - 向实例添加属性
导入类导入类
事件和侦听程序事件和侦听程序概念