MATLAB - 函数重载
MATLAB - 函数重载与方法重写
Section titled “MATLAB - 函数重载与方法重写”在 MATLAB 中,处理同名函数主要有两种方式:通过改变输入参数数量来实现函数重载(function overloading),以及在面向对象编程中实现方法重写(method overriding)。这使您能够创建灵活直观的接口,其中单个函数名可以根据其被调用的上下文调整其行为。
为何使用重载与重写?
Section titled “为何使用重载与重写?”这些技术是编写整洁、可复用且专业的 MATLAB 代码的基础。它们使您能够:
- 创建灵活的函数:设计一个能够根据输入数量或类型执行不同操作的单一函数,从而减少创建许多类似命名函数(例如,
addTwoNumbers、addThreeNumbers)的必要。 - 为自定义类定制行为:使您的自定义类对象表现得像 MATLAB 的内置类型一样。例如,您可以定义
plot或disp函数应如何专门为您的对象工作。 - 扩展现有功能:在面向对象编程中,子类可以提供其从父类继承的方法的专门版本(重写),从而在不改变父类的情况下定制其行为。
实现重载与重写
Section titled “实现重载与重写”MATLAB 的方法取决于您是在编写过程式脚本还是在定义类。
1. 使用可变参数 (nargin) 进行重载
Section titled “1. 使用可变参数 (nargin) 进行重载”对于标准函数(不在类中),您可以通过使用 nargin 关键字检查用户提供的输入参数数量来模拟重载。这允许单个函数展现不同的行为。
2. 面向对象编程 (OOP) 中的方法重写
Section titled “2. 面向对象编程 (OOP) 中的方法重写”在 OOP 中,当您创建一个类时,您可以定义与现有 MATLAB 函数(例如 plot、disp)或超类中的方法同名的方法。当您使用您的类对象调用该函数时,MATLAB 的调度机制会调用您类特有的方法。这被称为重写(overriding)。
- 主导参数规则(Dominant Argument Rule):当函数使用不同类的参数调用时,MATLAB 根据类层次结构确定要调用的方法。用户定义的类优先于内置类型。
- 实现:要重写一个函数,只需在您的
classdef文件中定义一个同名方法。此方法必须接受您的类对象作为参数。
示例 1:按输入数量的函数重载
Section titled “示例 1:按输入数量的函数重载”与其创建多个 add 方法,不如使用 nargin 或 varargin 在单个方法中处理可变数量的输入,这是一种更现代、更健壮的方法。下面是一个计算矩形或正方形面积的函数。
function area = calculateArea(width, height) % Calculates the area of a shape. % If one input is provided, it's treated as a square. % If two inputs are provided, it's treated as a rectangle.
% 计算形状的面积。 % 如果提供一个输入,则将其视为正方形。 % 如果提供两个输入,则将其视为矩形。
narginchk(1, 2); % Ensure 1 or 2 inputs are given % 确保给定 1 或 2 个输入
if nargin == 1 % Square: area = side^2 % 正方形:面积 = 边长^2 area = width^2; fprintf('Calculating area of a square with side %.2f\n', width); else % Rectangle: area = width * height % 矩形:面积 = 宽 * 高 area = width * height; fprintf('Calculating area of a rectangle with width %.2f and height %.2f\n', width, height); endend
% --- How to use it ---% --- 如何使用 ---area1 = calculateArea(5); % Called with one argument% 使用一个参数调用disp(['Area 1: ', num2str(area1)]);
area2 = calculateArea(5, 10); % Called with two arguments% 使用两个参数调用disp(['Area 2: ', num2str(area2)]);当您运行此代码时,MATLAB 的 nargin 检查会将流程导向正确的计算,从而有效地重载了 calculateArea 函数的行为。
示例 2:为自定义类重写 disp 函数
Section titled “示例 2:为自定义类重写 disp 函数”让我们创建一个 Patient 类并重写内置的 disp 函数,以便在 Patient 对象打印到控制台时提供自定义的、信息更丰富的显示。
classdef Patient properties Name string ID double Data double end
methods function obj = Patient(name, id, data) if nargin > 0 obj.Name = name; obj.ID = id; obj.Data = data; end end
% Override the built-in disp() function % 重写内置的 disp() 函数 function disp(obj) fprintf('--- Patient Record ---\n'); fprintf(' Name: %s\n', obj.Name); fprintf(' ID: %d\n', obj.ID); fprintf(' Data Points: %d\n', numel(obj.Data)); fprintf(' Mean Value: %.2f\n', mean(obj.Data)); fprintf('----------------------\n'); end endend
% --- How to use it ---% --- 如何使用 ---% Create an instance of the Patient class% 创建 Patient 类的实例p = Patient("John Doe", 123, [98.6, 99.1, 98.4, 98.7]);
% Now, just typing the variable name in the command window will call our custom disp method% 现在,只需在命令窗口中输入变量名就会调用我们自定义的 disp 方法disp(p);如果没有重写 disp 方法,MATLAB 将显示一个通用的对象属性列表。有了它,我们就能得到一个为我们的类量身定制的整洁、格式化的摘要。
示例 3:继承中的方法重写
Section titled “示例 3:继承中的方法重写”方法重写是继承的核心。子类可以提供其超类中方法的自己的版本。在这里,Circle 和 Rectangle 都继承自 Shape,但它们都提供了自己特定的 calculateArea 方法。
% --- Base Class: Shape.m ---% --- 基类:Shape.m ---classdef Shape methods function a = calculateArea(obj) disp('Area calculation not defined for a generic shape.'); % 泛型形状未定义面积计算。 a = NaN; % Not a Number % 非数字 end endend
% --- Subclass: Circle.m ---% --- 子类:Circle.m ---classdef Circle < Shape properties Radius end methods function obj = Circle(r) obj.Radius = r; end % Override calculateArea for Circle % 为 Circle 重写 calculateArea function a = calculateArea(obj) a = pi * obj.Radius^2; end endend
% --- Subclass: Rectangle.m ---% --- 子类:Rectangle.m ---classdef Rectangle < Shape properties Width Height end methods function obj = Rectangle(w, h) obj.Width = w; obj.Height = h; end % Override calculateArea for Rectangle % 为 Rectangle 重写 calculateArea function a = calculateArea(obj) a = obj.Width * obj.Height; end endend
% --- How to use it ---% --- 如何使用 ---shape = Shape();circle = Circle(10);rectangle = Rectangle(5, 8);
area1 = shape.calculateArea(); % Calls Shape's method% 调用 Shape 的方法area2 = circle.calculateArea(); % Calls Circle's method% 调用 Circle 的方法area3 = rectangle.calculateArea(); % Calls Rectangle's method% 调用 Rectangle 的方法
fprintf('Generic Shape Area: %.2f\n', area1);disp(['Circle Area: ', num2str(area2)]);disp(['Rectangle Area: ', num2str(area3)]);