示例—gelement类及其子类

前一节自定义了一个直线段类cline,直线段、圆弧、圆和多义线都可以看作基本的图形元素,这些图元具有公共的属性,如颜色等;有公共的方法,如绘图等。也有各自不同的属性和方法。考虑创建一个gelement类来描述图元类,用cline类和ccircle类描述直线段和圆,它们是图元类的子类。[大谦MATLAB,dqmatlab点com]

1 gelement类的设计

gelement类提供对其所有子类公共信息的保存和访问能力。因为不准备直接创建该类的实例,所以不需要扩展方法集。

gelement类有2个基本属性:

id 描述图形元素的编号。

color 描述图形元素的颜色。

这些信息对于gelement类的子对象来说是公共的,所以从父对象中进行控制,以避免在每个子类中定义相同的字段。当子类个数增加时,这非常有用。

类的属性在properties块中定义。

code.matlab
classdef gelement
    properties
        id
        color
    endend

为了实现数据保存和访问,该类需要包含下面几个方法。

构造函数

get和set函数

draw函数

gelement类为其子类提供数据保存,但不直接进行实例化。利用set, get和draw方法可以访问所保存的数据。不必实现gelement对象的所有方法,因为只有子类访问数据。

(1) gelement类的构造函数

code.matlab
classdef gelement
    …

    methods
        function g=gelement(varargin)
            % gelement对象的构造函数
            % g=gelement ()
            % g=gelement (g)
            % g=gelement (id, color)
            switch nargin
                case 0
                    % 如果没有输入参数,创建一个默认对象
                    g.id=0;
                    g.color=0;
                case 1
                    % 如果只有一个参数,返回它
                    if(isa(varargin{1}, gelement))
                        g=varargin{1};
                    else
                        error('参数类型错误。')
                    end
                case 2
                    % 用指定值创建对象
                    g.id=varargin{1};
                    g.color=varargin{2};
                otherwise
                    error('输入参数个数错误。')
            end
        endend
end

函数使用switch语句将3种可能情况组合到一起:

没有参数时,构造函数返回一个默认的gelement对象。

有一个参数时,对象简单地返回它。

有两个参数时,构造函数返回一个新的gelement对象。

不直接调用gelement类的构造函数,而是从子类构造函数中调用它,因为提供它们的目的是保存公共数据。

(2) gelement类属性的get方法

gelement类属性需要提供访问包含在gelement对象中数据的方法。下面的函数分别定义id和color属性的get方法。

code.matlab
function value=get.id(g)
    value=g.id;
end
function value=get.color(g)
    value=g.color;
end

(3) gelement类属性的set方法

gelement类属性的set方法被子类的set方法调用。

code.matlab
function g=set.id(g,value)
	  if isnumeric(value) && (value==fix(value))  && (value>0)
		  g.id=value;
	  else
		  error('属性值必须是正整数。')
	  end
end
function g=set.color(g,value)
	  if isnumeric(value)
		 g.color=value;
	  else
		 error('属性值必须是数值。')
	  end
end

(4) gelement类的draw方法

设计gelement类的draw方法,是为了从子类的draw方法中调用它。其目的是绘制图形元素。

code.matlab
function draw(a)
    % 绘制gelement对象
end

2.设计cline类

用cline类表示直线段。该类包括4个自己的属性和2个从父对象继承的属性。cline类自己的属性为startx, starty, endx和endy,分别表示直线段起点和终点的坐标;从gelement类继承的属性为id和color,分别表示直线段的编号和颜色。

code.matlab
classdef cline<gelement
    properties
       startx
       starty
       endx
       endy
    endend

cline类实现了下面一些方法:

构造函数

get和set方法

draw方法

(1) cline类的构造函数

cline类的构造函数用6个输入参数创建cline对象:

图元的编号;

颜色;

起点的x坐标;

起点的y 坐标;

终点的x 坐标;

终点的y 坐标。

构造函数必须从cline类构造函数内部创建一个gelement对象,作为cline对象的父对象。所以,cline构造函数必须调用gelement类的构造函数。被调用来创建cline对象的class函数将gelement对象作为父对象定义。

记住,gelement对象是在cline类构造函数的暂时工作空间中创建的,在cline类结构中作为字段(.gelement)保存。cline对象继承gelement类的字段,但gelement对象不会返回到基本工作空间。

code.matlab
classdef cline<gelement
    …

    methods
        function ln=cline(varargin)
            % cline类的构造函数
            % s=cline()
            % s=cline(ln)
            % s=cline(ID, Color,StartX, StartY, EndX, EndY)
            ln@gelement(varargin{1},varargin{2});
            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 6
                    % 用指定值创建对象
                    ln.startx=varargin{3};
                    ln.starty=varargin{4};
                    ln.endx=varargin{5};
                    ln.endy=varargin{6};
                otherwise
                    error('输入参数个数有误。')
            end
        endend
end

(2) 构造函数调用语法

cline类的构造函数可以用下面3种方式中的一种调用:

没有输入参数 如果调用时没有输入参数,则构造函数返回默认对象,字段为空。

输入参数是一个cline对象 如果输入参数为唯一的cline对象,则构造函数返回该输入参数。如果输入参数不是cline对象,会出错。

6个输入参数 如果有6个输入参数,构造函数用它们定义cline对象。

如果不满足上面3个条件,返回一个出错信息。

(3) cline类属性的get方法

与句柄图形类似,get方法提供了用"propertyname"类型的接口访问cline对象数据的一种途径。本例中,属性名与结构字段名类似,可以有很大的不同。也可以选择用get方法剔除某些字段,或者,如果该行为与设计吻合,可以从同一字段给多个属性名返回数据。

code.matlab
function value=get.startx(ln)
    value=ln.startx;
end
function value=get.starty(ln)
    value=ln.starty;
end
function value=get.endx(ln)
    value=ln.endx;
end
function value=get.endy(ln)
    value=ln.endy;
end

注意: gelement对象通过cline对象的gelement字段(s.gelement)进行访问。调用带父参数的class函数时,MATLAB自动创建该字段。

(4) cline类属性的set方法

set方法提供了与get方法类似的"propertyname"接口。

code.matlab
function ln=set.startx(ln,value)
	if isnumeric(value)
		ln.startx=value;
	else
		error('属性值必须是数值。')
	end
end

function ln=set.starty(ln,value)
	if isnumeric(value)
		ln.starty=value;
	else
		error('属性值必须是数值。')
	end
end

function ln=set.endx(ln,value)
	if isnumeric(value)
		ln.endx=value;
	else
		error('属性值必须是数值。')
	end
end

function ln=set.endy(ln,value)
	if isnumeric(value)
		ln.endy=value;
	else
		error('属性值必须是数值。')
	end
end

(4) cline类的draw方法

cline类的draw方法根据给定的直线段起点和终点坐标值绘直线段。

code.matlab
function draw(ln)
      x1=[ln.startx ln.endx];
      y1=[ln.starty ln.endy];
      cc=ln.color;
      line(x1,y1, 'Color',cc)
end

3.设计ccircle类

用ccircle类表示圆。该类包括3个自己的属性和2个从父对象继承的属性。ccircle类自己的属性为centerx, centery和radius,分别表示圆心坐标和半径;从gelement类继承的属性为id和color,分别表示圆的编号和颜色。

code.matlab
classdef ccircle<gelement
    properties
        centerx
        centery
        radius
    endend

ccircle类实现了下面一些方法:

构造函数

get和set方法

draw方法

(1) ccircle类的构造函数

ccircle类的构造函数用5个输入参数创建ccircle对象:

图元的编号;

颜色;

圆心的x坐标;

圆心的y 坐标;

半径;

构造函数必须从ccircle类构造函数内部创建一个gelement对象,作为ccircle对象的父对象。

code.matlab
classdef ccircle<gelement
    …
    methods
        function cc=ccircle(varargin)
            % ccircle类的构造函数
            % cc=ccircle()
            % cc=ccircle(c0)
            % cc=ccircle(ID, Color, CenterX, CenterY, Radius)
            cc@gelement(varargin{1},varargin{2});
            switch nargin
                case 0
                % 如果没有输入参数,创建一个默认对象
                    cc.centerx=0;
                    cc.centery=0;
                    cc.radius=0;
                case 1
                % 如果有一个参数,返回它
                    if(isa(varargin{1},'ccircle'))
                        cc=varargin{1};
                    else
                        error('输入参数不是ccircle对象。')
                    end
                case 5
                % 用指定值创建对象
                    cc.centerx=varargin{3};
                    cc.centery=varargin{4};
                    cc.radius=varargin{5};
                otherwise
                    error('输入参数个数有误。')
            end
        endend
end

(2) 构造函数调用语法

ccircle类的构造函数可以用下面3种方式中的一种调用:

没有输入参数 如果调用时没有输入参数,则构造函数返回默认对象,字段为空。

输入参数是一个ccircle对象 如果输入参数为唯一的ccircle对象,则构造函数返回该输入参数。如果输入参数不是ccircle对象,会出错。

6个输入参数 如果有6个输入参数,构造函数用它们定义ccircle对象。

如果不满足上面3个条件,返回一个出错信息。

(3) ccircle类的get方法

与句柄图形类似,get方法提供了用"propertyname"类型的接口访问ccircle对象数据的一种途径。本例中,属性名与结构字段名类似,可以有很大的不同。也可以选择用get方法剔除某些字段,或者,如果该行为与设计吻合,可以从同一字段给多个属性名返回数据。

code.matlab
function value=get.centerx(cc)
    value=cc.centerx;
end

function value=get.centery(cc)
    value=cc.centery;
end

function value=get.radius(cc)
    value=cc.radius;
end

注意: gelement对象通过ccircle对象的gelement字段(s.gelement)进行访问。调用带父参数的class函数时,MATLAB自动创建该字段。

(4) ccircle类的set方法

set方法提供了与get方法类似的"propertyname"接口。

code.matlab
function cc=set.centerx(cc,value)
	if isnumeric(value)
		cc.centerx=value;
	else
		error('属性值必须是数值。')
	end
end
function cc=set.centery(cc,value)
	if isnumeric(value)
		cc.centery=value;
	else
		error('属性值必须是数值。')
	end
end

function cc=set.radius(cc,value)
	if isnumeric(value) && (value>0)
		cc.radius=value;
	else
		error('属性值必须是正的数值。')
	end
end

(5) ccircle类的draw方法

ccircle类的draw方法根据给定的圆心坐标和半径绘圆。

code.matlab
function draw(cc)
    r=cc.radius;
    x1= cc.centerx-r;
    y1= cc.centery-r;
    x2=2*r;
    y2=2*r;
    c1=cc.color;
    rectangle('Position',[x1,y1,x2,y2], 'Curvature', [1 1], 'EdgeColor',c1);
end

4. 使用类

下面的代码首先生成一个cline对象和一个ccircle对象,并绘制它们的图形。然后将圆的颜色从红色变成绿色,并绘图;另外创建一个ccircle对象,设置其半径为2,绘图。

code.matlab
>> ln=cline(1,[0.5 0.5 0.5],1,0,8,5);
>> cc=ccircle(2,[1 0 0],5,5,3);
>> draw(ln)
>> hold on
>> draw(cc)
>> cc.color=[0 1 0];
>> draw(cc)
>> cc.radius=2;
>> draw(cc)
>> hold off
>> axis equal

运行程序,生成图5-1。

Document Image

图5-1 生成的图形