从超类静态方法

时间:2015-07-07 13:01:50

标签: matlab oop inheritance static-methods

我有一大堆由接口类链接在一起的小型相关类。所有类都实现了一个静态方法,该方法检索和处理特定于该类的数据。

该静态方法的输出需要至少以两种方式进行格式化。由于一种格式到另一种格式的转换总是相同而且相当微不足道(虽然很长),但我认为我将它作为超类中的具体,密封的静态方法实现。

然而,我遇到了以下问题:

% (in Superclass.m)
classdef SuperClass < handle

    methods (Static, Abstract)
        [arg1, arg2] = subsStaticMethod;            
    end

    methods (Sealed, Static)

        function [other_arg1, other_arg2] = supersStaticMethod

            % Get data here
            [arg1, arg2] = (???).subsStaticMethod

            % transform data here
            % ...

        end

    end

end

% (in Subclass.m)
classdef SubClass < SuperClass 

    methods (Static)

        function [arg1, arg2] = subsStaticMethod
            % Get class-specific data here
            % ...
        end

    end

end

据我所知,使用此设计无法调用SubClass.supersStaticMethod(),因为需要使用类名显式调用静态方法。换句话说,无法在上面的(???)中插入子类名称而不是SuperClass.supersStaticMethod

我尝试过的事情:

  • mfilename('class')这不起作用,因为它总会返回'SuperClass'
  • dbstack不包含实际从子类调用该方法的信息

我知道我可以通过使supersStaticMethod非静态,并在临时实例(如SubClass().supersStaticMethod())上调用该方法来解决此问题。或者在每个子类中创建一个小包装器方法,它只调用带有mfilename('class')的超类方法作为参数。或者其他100件看起来同样笨拙的东西。

但我真的很想知道是否有一些meta.class技巧或者可以干净利落地解决这个问题。我发现的只有this dated thread,它以编程方式处理MATLAB命令行以获取子类名称。

但是,我的类将在脚本/函数中使用,命令行使用仅用于调试目的......

有什么想法吗?

1 个答案:

答案 0 :(得分:1)

以下是我的hacky提案。我们的想法是将当前调用类存储在SuperClass的“静态变量”中,然后查询此字段并在feval中使用它来调用正确的子类'方法。几点说明:

  • 只要您没有并行执行某些计算(即在共享内存架构下一次从多个线程调用SubClass#.supersStaticMethod),它只能工作 - 在这种情况下,调用类字段将是不正当地改写。)
  • SuperClass的{​​{1}}不能是supersStaticMethod,但子类的版本可以
  • Sealed之后清除“静态变量”,以确保只从子类调用此方法。
  • 为了演示,我添加了SubClass.supersStaticMethod作为matlab.mixin.Heterogeneous的超类。
SuperClass

classdef SuperClass < handle & matlab.mixin.Heterogeneous

  properties (Abstract = true, Access = private, Constant = true)
    subclass@meta.class scalar;
  end

  methods (Static, Abstract)
    [arg1, arg2] = subsStaticMethod;
  end

  methods (Sealed, Static)
    function out = currentClass(input) % < the closest thing in MATLAB to a static variable
      persistent currentClass;
      if nargout == 0 && nargin == 1 % "setter" mode
        currentClass = input;
        out = [];
      else % "getter" mode
        out = currentClass;
      end      
    end
  end

  methods (Static)

    function [other_arg1, other_arg2] = supersStaticMethod

      % Who am I?
      whosCalling = SuperClass.currentClass();
      if isempty(whosCalling) || ~isa(whosCalling,'meta.class')
        [other_arg1,other_arg2] = deal(NaN);
        return
      else
        whosCalling = whosCalling.Name;
      end

      fprintf(1,'\nCalled from: %s\n', whosCalling);
      % Get data here
      [arg1, arg2] = feval([whosCalling '.subsStaticMethod']);

      % transform data here
      other_arg1 = arg1+arg2; other_arg2=[arg1(:);arg2(:)];
      fprintf(1,'other_arg1: %s, other_arg2: %s\n',...
                num2str(other_arg1), mat2str(other_arg2));

      % Clear the current class
      SuperClass.currentClass([]);
    end
  end

end

classdef SubClass1 < SuperClass

  properties (Constant)
    subclass@meta.class scalar = ?SubClass1;
  end

  methods (Static)    
    function [other_arg1, other_arg2] = supersStaticMethod
      SubClass1.currentClass(SubClass1.subclass);
      [other_arg1, other_arg2] = supersStaticMethod@SuperClass;
    end

    function [arg1, arg2] = subsStaticMethod
      arg1 = -1; arg2 = -2;
    end            

  end % static methods 
end % classdef

然后你可以这样测试:

classdef SubClass2 < SuperClass

  properties (Constant)
    subclass@meta.class scalar = ?SubClass2;
  end

  methods (Static)    
    function [other_arg1, other_arg2] = supersStaticMethod
      SubClass1.currentClass(SubClass2.subclass);
      [other_arg1, other_arg2] = supersStaticMethod@SuperClass;
    end

    function [arg1, arg2] = subsStaticMethod
      arg1 = 1; arg2 = 2;
    end            

  end % static methods 
end % classdef

输出结果为:

function q31269260

arr = [SubClass1, SubClass2];
for ind1 = 1:numel(arr)
  arr(ind1).supersStaticMethod;
end
%  arr.supersStaticMethod would not work because elements are treated as "instances" of
%  SuperClass, whose supersStaticMethod should not be called directly.