实现运算符重载以后,可以对对象进行类似数值运算和逻辑运算那样的操作。
1 如何定义运算符
在MATLAB中实现类对象的运算符,需要实现相关的类方法。每个运算符都有一个相关的函数,如“+”运算符相关的函数为plus.m。可以通过创建合适名称的类方法来实现任何运算符。表6-1列出了所有运算符和它们的相关函数名称。
表6-1 MATLAB运算符和相关函数
| 运 算 | 函 数 | 描 述 |
|---|---|---|
| a + b | plus(a,b) | 二元加 |
| a - b | minus(a,b) | 二元减 |
| -a | uminus(a) | 一元加 |
| +a | uplus(a) | 一元减 |
| a.*b | times(a,b) | 逐元素乘 |
| a*b | mtimes(a,b) | 矩阵相乘 |
| a./b | rdivide(a,b) | 逐元素右除 |
| a.\b | ldivide(a,b) | 逐元素左除 |
| a/b | mrdivide(a,b) | 矩阵右除 |
| a\b | mldivide(a,b) | 矩阵左除 |
| a.^b | power(a,b) | 逐元素求幂 |
| a^b | mpower(a,b) | 矩阵的幂 |
| a < b | lt(a,b) | 小于 |
| a > b | gt(a,b) | 大于 |
| a <= b | le(a,b) | 小于或等于 |
| a >= b | ge(a,b) | 大于或等于 |
| a ~= b | ne(a,b) | 不等于 |
| a == b | eq(a,b) | 等于 |
| a & b | and(a,b) | 逻辑与 |
| a | b | or(a,b) | 逻辑或 |
| ~a | not(a) | 逻辑非 |
| a:d:b | colon(a,d,b) | 冒号运算符 |
| a:b | colon(a,b) | |
| a' | ctranspose(a) | 复共轭转置 |
| a.' | transpose(a) | 矩阵转置 |
| [a b] | horzcat(a,b,...) | 水平聚合 |
| [a; b] | vertcat(a,b,...) | 垂向聚合 |
| a(s1,s2,...sn) | subsref(a,s) | 下标引用 |
| a(s1,...,sn)=b | subsasgn(a,s,b) | 下标赋值 |
| b(a) | subsindex(a) | 下标索引 |
2 操作中的对象优先级
自定义类具有比内置类更高的优先级。比如,假设q是一个double类对象,p是一个自定义类对象,下面两个表达式都会调用自定义类的plus方法,如果它定义了的话。
q + p
p + q
至于该方法是否能实现double型类对象与自定义类对象相加,取决于自定义类的plus方法怎么实现。
如果p和q是不同类的对象,MATLAB根据优先原则确定使用哪个方法。一般情况下,对象具有相同的优先级,根据从左至右的顺序调用方法。有两种情况下例外:
自定义类的优先级比MATLAB基础类和一些内置类的高。
自定义类可以通过定义InferiorClasses特性来指定它们相对于其它自定义类的相对优先级。该特性将定义的类的优先级放在指定的其它类前面。语法格式为:
classdef (InferiorClasses={?class1,?class2}) myClass
通过InferiorClasses特性指定myClass类的优先级在class1和class2的前面。
重载的运算符的优先级原则与MATLAB的原始定义相同。
3 示例 — cline类
下面通过定义一个名为cline的新类,实现直线段的定义和绘制,以及平移与缩放等几何变换。
cline类的数据结构
cline类用直线段的起点和终点坐标定义直线段。其对象ln是一个具有4个字段的结构。这4个字段分别为ln.startx, ln.starty, ln.endx和ln.endy。
properties
startx
starty
endx
endy
end
cline类的方法
cline类实现下面的方法:
构造函数cline
draw方法
重载的 +和 * 运算符
(1)cline类的构造函数
下面是cline类的构造函数cline。
methods
function ln=cline(varargin)
%cline对象的构造函数
%ln=cline(startx,starty,endx,endy)
switch nargin
case 0
%如果没有输入参数,创建一个默认对象
ln.startx=0;
ln.starty=0;
ln.endx=0;
ln.endy=0;
case 1
%如果只有一个参数,返回它
if(isa(varargin{1},'cline'))
ln=varargin{1};
else
error('输入参数不是cline对象。')
end
case 4
%用指定的坐标值创建对象
ln.startx=varargin{1};
ln.starty=varargin{2};
ln.endx=varargin{3};
ln.endy=varargin{4};
otherwise
error('输入参数个数错误。')
end
end
end
cline类有3个构造函数,它们具有不同的形式。
没有输入参数—如果调用没有参数的构造函数,它返回一个带空字段的cline对象。
输入参数为对象—如果调用输入参数为对象的构造函数,MATLAB返回该对象。
输入参数为直线段起点和终点的坐标值,class函数创建cline对象,并在后面由构造函数返回。下面是一个使用cline类构造函数的例子:
ln=cline(0,0,10,20)
这将创建一个起点坐标为(0,0),终点坐标为(10,20)的直线段。
(2)cline类的draw方法
function draw(ln)
x1=[ln.startx ln.endx];
y1=[ln.starty ln.endy];
line(x1,y1)
end
(3)重载算术运算符
对直线段进行平移和缩放操作时,实际上是对直线段的起点和终点坐标进行相加、相减或相乘计算,然后利用得到的结果进行绘图。本例中,为cline类定义了plus和mtimes方法,以便实现加和乘法等运算。
重载“+”运算符
对图形元素进行平移变换,实际上是对该土元的控制点进行平移变换,然后重新绘图。点的平移变换,实际上就是将该点的横坐标值和纵坐标值分别加上或减去x方向和y方向的平移值。定义向右和向上平移为正,向左和向下平移为负,可以将相加和相减运算统一为相加运算。直线段的控制点为其起点和终点,对直线段进行平移,只需计算其起点和终点的平移即可。
如果lno为cline类对象,v为以数组,其值分别表示x和y方向上平移值的大小。表达式lno+v调用plus函数,下面的函数为cline类定义“+”运算符。
function ln=plus(lno,v)
if(isa(lno,'cline'))
x1=lno.startx+v(1);
y1=lno.starty+v(2);
x2=lno.endx+v(1);
y2=lno.endy+v(2);
ln=cline(x1,y1,x2,y2);
else
error('参数类型错误。')
end
end
该函数首先判断第一个输入参数是不是cline类型的对象,如果是,对该对象所表示的直线段的起点和终点坐标值分别加上x方向和y 方向的平移值;如果不是,给出出错信息。
重载“*”运算符
放大或缩小直线段,实际上是将直线段的起点和终点坐标值乘上缩放系数,然后利用得到的坐标值进行绘图。
如果lno为cline类对象,v为以数组,其值分别表示x和y方向上的缩放比例。表达式lno*v调用mtimes.m函数,下面的函数为cline类定义“*”运算符。
function ln=mtimes(lno,v)
if(isa(lno,'cline'))
x1=lno.startx*v(1);
y1=lno.starty*v(2);
x2=lno.endx*v(1);
y2=lno.endy*v(2);
ln=cline(x1,y1,x2,y2);
else
error('参数类型错误。')
end
end
使用重载的运算符
下面用methods命令列出类的所有方法。
>> methods cline
类 cline 的方法:
cline draw mtimes plus
给定cline对象ln=cline(1,0,8,5),MATLAB在使用语句ln2=ln+[3 -1]时调用函数plus函数,使用语句ln3=ln*[2 2]时调用mtimes函数。然后分别绘这3条直线的图形。
>> ln=cline(1,0,8,5);
>> ln2=ln+[3 -1];
>> ln3=ln*[2 2];
>> draw(ln);
>> hold on
>> draw(ln2);
>> draw(ln3);
>> hold off
生成图6-1。图中最上面一条是最初生成的直线段,最下面一条是该直线段向下平移1个单位,向右平移3个单位后的图形,中间一条是放大两倍后的图形。
图6-1 生成的图形