34.5继承和聚合

Octave通过使用继承和聚合来支持使用类来构建新类。

类继承是从Octave使用提供的类构造函数中的函数。与多项式类的情况一样,Octaveprogrammer将创建一个包含该类所需数据字段的结构体,然后调用函数来指示要从结构体中创建的对象。创建现有对象的子对象是通过创建父类的对象并将该对象提供为类函数的第三个参数来完成的。

这很容易通过例子来证明。假设程序员需要FIR滤波器,即分子多项式但分母为1的滤波器。在传统的Octave编程中,这将按如下方式执行。

>>x=[某个数据向量];>>n=[某个系数向量];>>y=滤波器(n,1,x);

等效行为可以实现为类@FIRfilter。此类的构造函数是文件FIRfilter.m在类目录中@FIRfilter.

##-*-texinfo-*-##@deftypefn{}{}FIRfilter()##@deftypefnx{}{}FIRfilter(@var{p})##创建一个以多项式@var{p}为系数向量的FIR滤波器。##@end deftypefnfunction f=FIRfilter(p)if(nargin==0)p=@多项式([1]);elseif(!isa(p,“多项式”))错误(“@FIRfilter:p必须是多项式对象”);endif f.多项式=[];f=类(f,“FIRfilter”,p);结束函数

和前面一样,前导注释提供了类构造函数的文档。此构造函数与多项式类构造函数非常相似,只是将多项式对象作为第三个参数传递给函数,告诉OctaveFIRfilter类将从多项式类导出。FIR滤波器类本身没有任何数据字段,但它必须向作用考虑到@多项式构造函数将添加一个名为的元素多项式的到对象结构体@FIRfilter使用伪字段对结构体进行just初始化多项式的其稍后将被覆盖。

请注意,示例代码总是提供不提供参数的情况。这一点很重要,因为Octave在从保存的文件中加载对象以确定继承结构体时,将调用不带参数的构造函数。

一个类可以是多个类的子类(详见),并且可以嵌套继承。除了内存或其他物理问题外,父级对象的数量或嵌套级别没有限制。

对于FIRfilter类,则需要对对象显示进行更多控制。因此显示方法而不是disp方法重载(详见类方法). 一个简单的例子可能是

函数显示(f)printf(“%s.多项式”,输入名称(1));disp(f多项式);结束函数

请注意FIRfilter的显示方法依赖于disp的方法多项式的类以实际显示滤波器系数。此外,请注意,在显示方法它使方法从线开始printf(“%s=”,inputname(1))以与Octave的设置一致,Octave打印要显示的变量名和值。一般情况下,不建议重载显示作用

 
: display (obj)

显示对象的内容obj以其名称为前缀。

Octave解释器调用显示只要需要就可以在屏幕上显示类。通常,这将是一个不以分号结尾以抑制输出的语句。例如

myclass(…)

myobj=myclass(…)

通常,用户定义的类应该重载disp方法使默认输出无效:

myobj=myclass(…)⇒ myobj=<class myclass>

当重载时显示方法,必须注意正确显示对象的名称。这可以通过使用inputname作用

详见: disp, , subsref, 潜艇.

一旦构造函数和显示方法存在,就可以创建类的实例。也可以检查类类型并检查底层结构体。

octave:1>f=FIRfilter(多项式([1 1 1]/3))f.多项式=0.33333+0.33333*X+0.33333*X^2octave(f)ans=FIRfilteroctave3>isa(f,“FIRfilter”)ans=1octave4>isa“f,“多项式”)ans=1octave5>结构体(f)uns=包含字段的标量结构体:多项式=0.33333+0.33333*X+0.33333*X^2

使这个类可用的惟一方法是处理数据的方法。但在此之前,通常还需要一种更改存储在类中的数据的方法。从于底层结构体中的字段默认情况下是私有的,因此有必要提供一种访问字段的机制。这个subsref方法可以用于这两个任务。

函数r=subsref(f,x)开关(x.type)情况“()”n=f多项式;r=滤波器(n.poly,1,x.subs{1});case“.”fld=x.subs;if(!strcmp(fld,“polynomial”))错误('@FIRfilter/subsref:无效属性“%s”',fld);endif r=f多项式;否则错误(“@FIRfilter/subsref:FIR滤波器的无效下标类型”);endswitchendfunction

这个()case允许我们使用提供给构造函数的多项式来过滤数据。

Octave:2>f=FIRfilter(多项式([1 1 1]/3));octave:3>x=一(5,1);octave:4>y=f(x)y=0.33333 0.66667 1.00000 1.00000 1.000000

这个.case允许我们查看多项式字段的内容。

Octave:1>f=FIRfilter(多项式([1 1 1]/3));Octave:2>f。多项式=0.33333+0.33333*X+0.33333*X ^2

为了更改对象的内容subs方法是必要的。例如,以下代码使多项式字段公开可写

函数fout=subsasgn(f,index,val)开关(index.type)case“.”fld=index.subs;if(!strcmp(fld,“polynomial”))错误('@FIRfilter/subsasgn:无效属性“%s”',fld);endif-fout=f;fout.多项式=val;否则错误(“@FIRfilter/subsasgn:无效的索引类型”)endswitchendfunction

因此

Octave:1>f=FIRfilter();octave:2>f.多项式=多项式([1 2 3])f.多项式=1+2*X+3*X^2

定义FIRfilter类作为多项式类的子类意味着FIRfilter对象可以在多项式对象可能使用的任何地方使用。这不是过滤器的正常使用。使用聚合而不是继承可能是一种更明智的设计方法。在这种情况下,多项式只是类结构体中的一个域。聚合情况的类构造函数可能是

##-*-texinfo-*-##@deftypefn{}{}FIRfilter()##@deftypefnx{}{}FIRfilter(@var{p})##创建一个以多项式@var{p}为系数向量的FIR滤波器。##@end deftypefnfunction f=FIRfilter(p)if(nargin==0)f.多项式=@多项式([1]);else-if(!isa(p,“多项式”))错误(“@FIRfilter:p必须是多项式对象”);endif f.多项式=p;endif f f=class(f,“FIRfilter”);结束函数

对于这个例子,只有构造函数需要更改,所有其他类方法保持不变。


版权所有 © 2024-2025 Octave中文网

ICP备案/许可证号:黑ICP备2024030411号-2