前一节自定义了一个直线段类cline,直线段、圆弧、圆和多义线都可以看作基本的图形元素,这些图元具有公共的属性,如颜色等;有公共的方法,如绘图等。也有各自不同的属性和方法。考虑创建一个gelement类来描述图元类,用cline类和ccircle类描述直线段和圆,它们是图元类的子类。[大谦MATLAB,dqmatlab点com]
1 gelement类的设计
gelement类提供对其所有子类公共信息的保存和访问能力。因为不准备直接创建该类的实例,所以不需要扩展方法集。
gelement类有2个基本属性:
id 描述图形元素的编号。
color 描述图形元素的颜色。
这些信息对于gelement类的子对象来说是公共的,所以从父对象中进行控制,以避免在每个子类中定义相同的字段。当子类个数增加时,这非常有用。
类的属性在properties块中定义。
classdef gelement
properties
id
color
end
…
end
为了实现数据保存和访问,该类需要包含下面几个方法。
构造函数
get和set函数
draw函数
gelement类为其子类提供数据保存,但不直接进行实例化。利用set, get和draw方法可以访问所保存的数据。不必实现gelement对象的所有方法,因为只有子类访问数据。
(1) gelement类的构造函数
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
end
…
end
end
函数使用switch语句将3种可能情况组合到一起:
没有参数时,构造函数返回一个默认的gelement对象。
有一个参数时,对象简单地返回它。
有两个参数时,构造函数返回一个新的gelement对象。
不直接调用gelement类的构造函数,而是从子类构造函数中调用它,因为提供它们的目的是保存公共数据。
(2) gelement类属性的get方法
gelement类属性需要提供访问包含在gelement对象中数据的方法。下面的函数分别定义id和color属性的get方法。
function value=get.id(g)
value=g.id;
end
function value=get.color(g)
value=g.color;
end
(3) gelement类属性的set方法
gelement类属性的set方法被子类的set方法调用。
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方法中调用它。其目的是绘制图形元素。
function draw(a)
% 绘制gelement对象
end
2.设计cline类
用cline类表示直线段。该类包括4个自己的属性和2个从父对象继承的属性。cline类自己的属性为startx, starty, endx和endy,分别表示直线段起点和终点的坐标;从gelement类继承的属性为id和color,分别表示直线段的编号和颜色。
classdef cline<gelement
properties
startx
starty
endx
endy
end
…
end
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对象不会返回到基本工作空间。
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
end
…
end
end
(2) 构造函数调用语法
cline类的构造函数可以用下面3种方式中的一种调用:
没有输入参数 如果调用时没有输入参数,则构造函数返回默认对象,字段为空。
输入参数是一个cline对象 如果输入参数为唯一的cline对象,则构造函数返回该输入参数。如果输入参数不是cline对象,会出错。
6个输入参数 如果有6个输入参数,构造函数用它们定义cline对象。
如果不满足上面3个条件,返回一个出错信息。
(3) cline类属性的get方法
与句柄图形类似,get方法提供了用"propertyname"类型的接口访问cline对象数据的一种途径。本例中,属性名与结构字段名类似,可以有很大的不同。也可以选择用get方法剔除某些字段,或者,如果该行为与设计吻合,可以从同一字段给多个属性名返回数据。
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"接口。
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方法根据给定的直线段起点和终点坐标值绘直线段。
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,分别表示圆的编号和颜色。
classdef ccircle<gelement
properties
centerx
centery
radius
end
…
end
ccircle类实现了下面一些方法:
构造函数
get和set方法
draw方法
(1) ccircle类的构造函数
ccircle类的构造函数用5个输入参数创建ccircle对象:
图元的编号;
颜色;
圆心的x坐标;
圆心的y 坐标;
半径;
构造函数必须从ccircle类构造函数内部创建一个gelement对象,作为ccircle对象的父对象。
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
end
…
end
end
(2) 构造函数调用语法
ccircle类的构造函数可以用下面3种方式中的一种调用:
没有输入参数 如果调用时没有输入参数,则构造函数返回默认对象,字段为空。
输入参数是一个ccircle对象 如果输入参数为唯一的ccircle对象,则构造函数返回该输入参数。如果输入参数不是ccircle对象,会出错。
6个输入参数 如果有6个输入参数,构造函数用它们定义ccircle对象。
如果不满足上面3个条件,返回一个出错信息。
(3) ccircle类的get方法
与句柄图形类似,get方法提供了用"propertyname"类型的接口访问ccircle对象数据的一种途径。本例中,属性名与结构字段名类似,可以有很大的不同。也可以选择用get方法剔除某些字段,或者,如果该行为与设计吻合,可以从同一字段给多个属性名返回数据。
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"接口。
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方法根据给定的圆心坐标和半径绘圆。
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,绘图。
>> 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。
图5-1 生成的图形