Skip to content

MATLAB - 类和对象

MATLAB 中的面向对象编程 (OOP) 是一种强大的范式,用于设计和实现复杂的软件系统。通过创建类和对象,您可以构建模块化、可重用和可维护的代码,以模拟现实世界实体及其交互。

  • 类(Class):创建对象的模板或蓝图。它定义了一组对象将拥有的属性(数据)和方法(函数)。
  • 对象(Object):类的一个实例。它在属性中存储特定数据,并可以使用其方法执行操作。
  • 封装(Encapsulation):将数据(属性)和操作该数据的方法捆绑到一个单一的单元(对象)中。这隐藏了内部复杂性并保护数据免受未经授权的访问。
  • 继承(Inheritance):从现有类(超类)创建新类(子类)。子类继承超类的属性和方法,从而实现代码重用和创建专门化的类。
  • 多态(Polymorphism):不同类以各自独特方式响应相同方法调用的能力。这使得代码具有灵活性和可扩展性。

现代类定义在 .m 文件中,文件名与类名匹配。定义以 classdef 关键字开始。

让我们创建一个实用的 BankAccount 类来演示其关键特性。创建一个名为 BankAccount.m 的文件。

% BankAccount.m
classdef BankAccount < handle
% 一个表示简单银行账户的句柄类。
properties (Access = public)
AccountHolder string
end
properties (SetAccess = private)
% 可从外部读取,但只能在内部设置。
AccountNumber (1,1) double
Balance (1,1) double = 0.0
end
properties (Constant)
% 所有实例共享的常量属性。
BankName string = "MATLAB Central Bank"
end
methods
% --- 构造函数方法 ---
function obj = BankAccount(holderName, initialDeposit)
% 创建 BankAccount 类的实例。
arguments
holderName (1,1) string
initialDeposit (1,1) double {mustBeNonnegative} = 0
end
obj.AccountHolder = holderName;
obj.Balance = initialDeposit;
% 分配一个唯一的账号(简单示例)
obj.AccountNumber = randi([1e5, 1e6-1]);
fprintf('Welcome, %s! Account #%d created with a balance of $%.2f.\n', ...
obj.AccountHolder, obj.AccountNumber, obj.Balance);
end
% --- 公共方法 ---
function deposit(obj, amount)
% 存钱到账户中。
arguments
obj BankAccount
amount (1,1) double {mustBePositive}
end
obj.Balance = obj.Balance + amount;
fprintf('Deposited $%.2f. New balance: $%.2f.\n', amount, obj.Balance);
end
function withdraw(obj, amount)
% 从账户中取钱。
arguments
obj BankAccount
amount (1,1) double {mustBePositive}
end
if amount > obj.Balance
error('BankAccount:InsufficientFunds', ...
'Withdrawal amount of $%.2f exceeds current balance of $%.2f.', ...
amount, obj.Balance);
end
obj.Balance = obj.Balance - amount;
fprintf('Withdrew $%.2f. New balance: $%.2f.\n', amount, obj.Balance);
end
end
end
  • classdef BankAccount < handle:这定义了一个名为 BankAccount 的类,它继承自 handle。句柄类的行为类似于引用;当您复制一个句柄对象时,您复制的是引用,而不是对象的数据。两个副本都指向相同的底层数据。这与默认的值类不同,值类在复制时会创建完全独立的副本。
  • properties (Attribute):属性块用于定义数据。属性控制它们的行为:
  • - **`Access = public`**:可以从任何地方读取和写入(例如 `AccountHolder`)。
  • - **`SetAccess = private`**:可以从任何地方读取,但只能由类内部的方法修改(例如 `Balance`、`AccountNumber`)。这是封装的关键部分。
  • - **`Constant`**:该值是固定的,不能更改(例如 `BankName`)。
  • methods:方法块包含对对象进行操作的函数。任何非静态方法的第一个参数始终是对象本身(通常命名为 obj)。
  • 构造函数(BankAccount(...)):一个与类同名的特殊方法。当您创建对象时(例如 myAccount = BankAccount(...)),它会自动被调用。
  • arguments 块:一种现代且强烈推荐的特性,用于验证方法输入,使您的代码更健壮且具有自文档性。

您现在可以从 MATLAB 命令窗口或脚本创建并与 BankAccount 对象交互。

% Create two accounts
account1 = BankAccount("Alice", 200.0);
Welcome, Alice! Account #157363 created with a balance of $200.00.
account2 = BankAccount("Bob");
Welcome, Bob! Account #935069 created with a balance of $0.00.
% Perform operations
account1.deposit(50.0);
Deposited $50.00. New balance: $250.00.
account2.deposit(1000.0);
Deposited $1000.00. New balance: $1000.00.
account1.withdraw(30.0);
Withdrew $30.00. New balance: $220.00.
% Trying to modify a private-set property will fail
account1.Balance = 5000;
Error using BankAccount/set.Balance
You cannot set the read-only property 'Balance' of BankAccount.
% Trying an invalid operation
account1.withdraw(300.0);
Error using BankAccount/withdraw (line 69)
Withdrawal amount of $300.00 exceeds current balance of $220.00.

MATLAB 提供了在运行时检查和使用对象的函数。

class 函数将变量的类名作为字符串返回。这对于类型检查很有用。

myAccount = BankAccount("Charlie");
Welcome, Charlie! Account #489764 created with a balance of $0.00.
className = class(myAccount)
className =
"BankAccount"
someNumber = 42;
class(someNumber)
ans =
'double'

isobject 函数如果输入变量是任何 MATLAB 类的实例,则返回逻辑 true,否则返回 false。

isobject(myAccount)
ans =
logical
1
myStruct = struct('field', 'value');
isobject(myStruct)
ans =
logical
0

isa(obj, 'ClassName'):检查特定类类型

Section titled “isa(obj, 'ClassName'):检查特定类类型”

isa 函数比 isobject 更具体。如果对象是指定类或其任何子类的实例,则返回 true。这是检查对象类型的首选方法。

isa(myAccount, 'BankAccount')
ans =
logical
1
isa(myAccount, 'handle') % BankAccount inherits from handle
ans =
logical
1
isa(myAccount, 'double')
ans =
logical
0
  • 测试:使用 MATLAB 单元测试框架为您的类编写自动化测试。这确保您的方法按预期工作并防止回归。
  • 包(Packages):对于大型项目,将相关的类组织到包中(以 + 开头的文件夹)。这可以防止命名冲突并分组功能,例如 +mybank/BankAccount.m。
  • 静态方法(Static Methods):使用 Static 属性定义属于类但不属于特定实例的方法。它们对于与类相关的实用函数很有用。
  • 事件和监听器(Events and Listeners):通过在类中定义事件并创建在事件触发时做出反应的监听器来实现在观察者设计模式。