我有一大堆由接口类链接在一起的小型相关类。所有类都实现了一个静态方法,该方法检索和处理特定于该类的数据。
该静态方法的输出需要至少以两种方式进行格式化。由于一种格式到另一种格式的转换总是相同而且相当微不足道(虽然很长),但我认为我将它作为超类中的具体,密封的静态方法实现。
然而,我遇到了以下问题:
% (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命令行以获取子类名称。
但是,我的类将在脚本/函数中使用,命令行使用仅用于调试目的......
有什么想法吗?
答案 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.