34.1 创建类

本章通过一个为多项式设计的自定义类来说明用户定义类和面向对象编程。选择这个类是因为它的简单性,不会不必要地分散对 Octave 编程特性的讨论。即便如此,在介绍 Octave 面向对象编程的语法和技术之前,有必要先了解一下多项式类的一些背景目标。

多项式类用于表示如下形式的多项式:

a0 + a1 * x + a2 * x^2 + ... + an * x^n

其中 a0、a1 等是实数标量。因此多项式可以用向量表示:

a = [a0, a1, a2, ..., an];

有了这些规定,就可以开始为多项式类编写构造函数了。Octave 中所有的面向对象类都必须位于一个目录中,该目录的名称是类名前面加上 ‘@’ 符号。例如,多项式类的所有方法都将定义在 @polynomial 目录中。

类的构造函数必须与类本身同名;在本例中,构造函数位于 @polynomial/polynomial.m 文件中。理想情况下,即使在不带参数调用构造函数时,它也应返回一个有效的对象。多项式类的构造函数可能如下所示:

## -*- texinfo -*-
## @deftypefn  {} {} polynomial ()
## @deftypefnx {} {} polynomial (@var{a})
## 创建一个表示多项式的多项式对象
##
## @example
## a0 + a1 * x + a2 * x^2 + @dots{} + an * x^n
## @end example
##
## @noindent
## 根据系数向量 [a0 a1 a2 @dots{} an] 创建。
## @end deftypefn

function p = polynomial (a)

  if (nargin == 0)
    p.poly = 0;
    p = class (p, "polynomial");
  else
    if (isa (a, "polynomial"))
      p = a;
    elseif (isreal (a) && isvector (a))
      p.poly = a(:).';  # 强制为行向量
      p = class (p, "polynomial");
    else
      error ("@polynomial: A must be a real vector");
    endif
  endif

endfunction

请注意,构造函数的返回值必须是 class 函数的输出。class 函数的第一个参数是一个结构体,第二个参数是类本身的名称。调用类构造函数创建实例的示例如下:

p = polynomial ([1, 0, 1]);

方法由类目录中的 m 文件定义,并且可以像其他任何 m 文件一样包含内嵌文档。构造函数的帮助可以通过单独使用构造函数名称来获取,也就是说,对于多项式构造函数,help polynomial 将返回帮助字符串。通过使用类目录名后接方法名,可以将帮助限定到特定的类。例如,help @polynomial/polynomial 是显示多项式构造函数帮助字符串的另一种方式。这第二种方法是获取类的重载方法和函数帮助的唯一途径。

同样的规范机制可以在 Octave 期望函数名的任何地方使用。例如,type @polynomial/disp 会将多项式类的 disp 方法的代码打印到屏幕上,而 dbstop @polynomial/disp 将在多项式类的 disp 方法的第一个可执行行设置断点。

要检查变量是否属于用户类,可以使用 isobjectisa 函数。例如:

p = polynomial ([1, 0, 1]);
isobject (p)
  ⇒   1
isa (p, "polynomial")
  ⇒   1
 
tf = isobject (x)

如果 x 是类对象,则返回 true。

另请参阅: class, typeinfo, isa, ismethod, isprop.

类的可用方法可以通过 methods 函数来显示。

 
methods (obj)
methods ("classname")
methods (…, "-full")
mtds = methods (…)

列出对象 obj 或指定类 classname 的公有方法的名称。

obj 可以是 Octave 类对象或 Java 对象。classname 可以是 Octave 类或 Java 类的名称。

如果给定了可选参数 "-full",则 Octave 会返回完整的方法签名,包括输出类型、方法名称以及输入参数的数量和类型。

当不带输出参数调用时,methods 将方法名称列表打印到屏幕上。否则,输出参数 mtds 以字符串元胞数组的形式包含该列表。

另请参阅: ismethod, properties, fieldnames.

要查询用户类是否存在特定方法,可以使用 ismethod 函数。

 
tf = ismethod (obj, method)
tf = ismethod (class_name, method)

如果字符串 method 是对象 obj 或类 clsname 的有效方法,则返回 true。

另请参阅: isprop, isobject, isjava, methods.

对于多项式类,拥有一个计算其根的方法是合理的。

function r = roots (p)
  r = roots (fliplr (p.poly));
endfunction

我们可以通过调用来检查 roots 方法是否存在:

p = polynomial ([1, 0, 1]);
ismethod (p, "roots")
  ⇒   1

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

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