【问题标题】:Call subclass static method from inside superclass static method从超类静态方法内部调用子类静态方法
【发布时间】:2015-07-07 13:01:50
【问题描述】:

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

该静态方法的输出需要至少以两种方式格式化。由于从一种格式到另一种格式的转换总是相同且相当琐碎(虽然很长),我想我会在超类中将它实现为一个具体的、密封的、静态方法。

但是,我遇到了以下问题:

% (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 命令行以获取子类名称。

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

有什么想法吗?

【问题讨论】:

    标签: matlab oop inheritance static-methods


    【解决方案1】:

    以下是我的 hacky 建议。想法是将当前调用类存储在SuperClass 的“静态变量”中,然后查询该字段并在feval 中使用它来调用正确的子类方法。几个注意事项:

    • 只有在您不进行并行计算时才能工作(即在共享内存架构下一次从多个线程调用SubClass#.supersStaticMethod - 在这种情况下,调用类字段将被不规则地覆盖)。
    • SuperClasssupersStaticMethod 不能是 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.
    

    输出是:

    Called from: SubClass1
    other_arg1: -3, other_arg2: [-1;-2]
    
    Called from: SubClass2
    other_arg1: 3, other_arg2: [1;2]
    

    【讨论】:

    • 谢谢!这是一个有点老的问题,我忘记了它是关于什么的......给点时间再追上。
    • 没问题,我看到没有答案被接受所以我决定试一试:)
    • @RodyOldenhuis 好吗? :)
    • 哈哈,抱歉……我会尽快回复你。
    • 看起来相当不错,实际上......我会半盲地接受你的答案,我会在我最终以不同方式解决的现在古老的问题中对其进行测试。
    猜你喜欢
    • 1970-01-01
    • 2012-05-24
    • 1970-01-01
    • 1970-01-01
    • 1970-01-01
    • 2017-09-14
    • 2023-03-15
    • 1970-01-01
    • 2011-01-17
    相关资源
    最近更新 更多