【问题标题】:Access to methods and properties for classes with overloaded index reference访问具有重载索引引用的类的方法和属性
【发布时间】:2012-01-13 15:07:51
【问题描述】:

我想通过(){} 为我的一个MATLAB 类重载索引。这可以通过为该类实现subsref 来实现,并且效果很好。

但是,我还想为此类保留通过. 进行索引的默认行为(即访问方法和属性)。我尝试使用以下代码:

function x = subsref(this, S)
    if strcmp(S(1).type, '{}')
        % My own implementation here
    elseif strcmp(S(1).type, '()')
        % My own implementation here
    elseif strcmp(S(1).type, '.')
        x = builtin('subsref', this, S);
    else
        error('Unknown index variant.');
end

但是,这不起作用,因为我不知道对builtin('subsref', this, S) 的调用将返回多少个输出参数。特别是,我的类的方法可能返回可变数量的参数,输出参数的数量取决于其输入参数的数量和值。 MATLAB example for subsref(断开的链接)备注:

当你为一个类实现 subsref 方法时,你必须显式地实现所有下标引用 [...]

这真的是唯一可能的解决方案吗?对于复杂的方法,这基本上意味着复制大量的逻辑。在我的情况下,这绝对是不可维护的(具有大量方法和属性的大型类)。

注意:我知道这都是关于语法糖的,我总是可以使用标准方法调用而不是重载 (){}

【问题讨论】:

  • 重载 subsref 几乎从来都不是一个好主意。你会比你可以预料的更头痛。如果您可以描述为什么要尝试重载 subsref 以及您要解决的问题,那么有人可能会提出比这种方法更好的解决方案。
  • @Kavka:操作符重载通常是一个困难的话题,关于它的优缺点一直存在长期争论。就我而言,我正在编写一个类似列表的对象,通过(){} 的索引是自然扩展。正如我在原帖中所说,重载运算符通常与语法糖有关,使用普通方法/属性也可以实现相同的目的。然而,如果实现得当,重载运算符可以使代码更短更清晰。
  • 我的两分钱:特别是对于 Matlab,虽然 subsasgn 和 subsref 很繁琐(即使对于运算符重载机制),但在某些情况下它们是值得的,因为索引在 Matlab 中非常惯用。特别是如果您正在执行嵌套索引。对于使用索引的多态代码来说,这几乎是必需的。我只为少数几个类(可能是其中的 1%)做过,但我所有都使用那些被覆盖的运算符。

标签: matlab operator-overloading


【解决方案1】:

对于部分修复,我认为您可以使用 nargout 来推迟调用者,这通常会知道。任何捕获多个输出的函数都必须在调用时知道它正在捕获多少。

这不会让您在命令行中显示多个参数,但只要您像在大多数代码中一样捕获返回的值,它就应该可以工作。

function varargout = subsref(this, S)
   switch S(1).type
      ...
      case '.'
         varargout = cell(1, nargout);
         if nargout == 0
             builtin('subsref', this, S);
         else
             [varargout{:}] = builtin('subsref', this, S);
         end
   end
end

请注意:此代码未经测试,并且在 subsref/subsasgn 内容中存在一堆挑剔的边缘案例。

【讨论】:

  • 一个好主意。如果调用者提供了错误数量的参数,错误消息可能会令人困惑(因为他们会在subsref 中得到一个错误,而不是在他们认为他们正在调用的方法中),但我想你必须忍受如果你重载运算符。
猜你喜欢
  • 2020-01-01
  • 2010-11-25
  • 2011-12-10
  • 2011-07-03
  • 1970-01-01
  • 1970-01-01
  • 1970-01-01
  • 1970-01-01
  • 1970-01-01
相关资源
最近更新 更多