运算符重载

实现运算符重载以后,可以对对象进行类似数值运算和逻辑运算那样的操作。

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。

code.matlab
properties
   startx
   starty
   endx
   endy
end

cline类的方法

cline类实现下面的方法:

构造函数cline

draw方法

重载的 +和 * 运算符

(1)cline类的构造函数

下面是cline类的构造函数cline。

code.matlab
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类构造函数的例子:

code.matlab
ln=cline(0,0,10,20)

这将创建一个起点坐标为(0,0),终点坐标为(10,20)的直线段。

(2)cline类的draw方法

code.matlab
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类定义“+”运算符。

code.matlab
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类定义“*”运算符。

code.matlab
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命令列出类的所有方法。

code.matlab
>> 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条直线的图形。

code.matlab
>> 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个单位后的图形,中间一条是放大两倍后的图形。

Document Image

图6-1 生成的图形