34.2 类方法

有许多基本的类方法可以(也应当)被定义,以便查询和设置类的内容。其中最基本的是 disp 方法。每当一个类需要显示在屏幕上时,Octave 就会使用 disp 方法。这通常是不以分号结尾的 Octave 表达式的结果。如果未定义此方法,那么 Octave 在显示类的内容时将不会打印任何内容,这可能会令人困惑。

以下是一个多项式类的 disp 方法示例:

function disp (p)

  a = p.poly;
  first = true;
  for i = 1 : length (a);
    if (a(i) != 0)
      if (first)
        first = false;
      elseif (a(i) > 0 || isnan (a(i)))
        printf (" +");
      endif
      if (a(i) < 0)
        printf (" -");
      endif
      if (i == 1)
        printf (" %.5g", abs (a(i)));
      elseif (abs (a(i)) != 1)
        printf (" %.5g *", abs (a(i)));
      endif
      if (i > 1)
        printf (" X");
      endif
      if (i > 2)
        printf (" ^ %d", i - 1);
      endif
    endif
  endfor

  if (first)
    printf (" 0");
  endif
  printf ("\n");

endfunction

为了与 Octave 图形句柄类保持一致,一个类还应该定义 getset 方法。get 方法接受一个或两个参数。第一个参数是相应类的对象。如果没有给出第二个参数,那么该方法应返回一个包含该类所有属性的结构体。如果给出了可选的第二个参数,则该参数应为属性名称,并应检索指定的属性。

function val = get (p, prop)

  if (nargin < 1)
    print_usage ();
  endif

  if (nargin == 1)
    val.poly = p.poly;
  else
    if (! ischar (prop))
      error ("@polynomial/get: PROPERTY must be a string");
    endif

    switch (prop)
      case "poly"
        val = p.poly;
      otherwise
        error ('@polynomial/get: invalid PROPERTY "%s"', prop);
    endswitch
  endif

endfunction

类似地,set 方法的第一个参数应当是一个对象,其余参数应当是属性/值对。

function pout = set (p, varargin)

  if (numel (varargin) < 2 || rem (numel (varargin), 2) != 0)
    error ("@polynomial/set: expecting PROPERTY/VALUE pairs");
  endif

  pout = p;
  while (numel (varargin) > 1)
    prop = varargin{1};
    val  = varargin{2};
    varargin(1:2) = [];
    if (! ischar (prop) || ! strcmp (prop, "poly"))
      error ("@polynomial/set: invalid PROPERTY for polynomial class");
    elseif (! (isreal (val) && isvector (val)))
      error ("@polynomial/set: VALUE must be a real vector");
    endif

    pout.poly = val(:).';  # 强制为行向量
  endwhile

endfunction

请注意,Octave 不实现按引用传递;因此,要修改对象需要使用 set 方法的返回值进行赋值语句。

p = set (p, "poly", [1, 0, 0, 0, 1]);

set 方法使用了类的 subsasgn 方法,因此也必须定义此方法。subsasgn 方法将在下一节(见 对象索引)中进行更详细的讨论。

最后,用户类可以被视为一种特殊类型的结构体,并且可以像结构体一样保存到文件中。例如:

p = polynomial ([1, 0, 1]);
save userclass.mat p
clear p
load userclass.mat

saveload 支持的所有文件格式都被支持。在某些情况下,用户类可能包含一个无需保存的字段,或者一个需要在保存前初始化的字段。这可以通过类的 saveobj 方法来实现。

 
b = saveobj (a)

一个类的方法,用于在将对象保存到文件之前对其进行操作。

当对象 a 使用 save 函数保存时,会调用 saveobj 函数。saveobj 的一个使用示例是删除对象中没有保存意义的字段,或者用于确保在保存对象之前初始化对象的某些字段。例如:

function b = saveobj (a)
  b = a;
  if (isempty (b.field))
     b.field = initfield (b);
  endif
endfunction

另请参阅: loadobjclass

saveobj 在将类保存到文件之前被调用。类似地,loadobj 方法在从文件加载类之后立即被调用,并可用于确保将任何被删除的字段重新插入到用户对象中。

 
b = loadobj (a)

一个类的方法,用于在从文件加载对象后对其进行操作。

当对象 a 使用 load 函数加载时,会调用 loadobj 函数。loadobj 的一个使用示例是向对象中添加那些不适合保存的字段。例如:

function b = loadobj (a)
  b = a;
  b.addmissingfield = addfield (b);
endfunction

另请参阅: saveobjclass


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

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