从超类静态方法内部调用子类静态方法
Call subclass static method from inside superclass static method
我有一大堆小的、相关的 class 通过接口 class 链接在一起。所有 classes 都实现了一个静态方法,该方法检索和处理特定于 class 的数据。
该静态方法的输出至少需要以两种方式进行格式化。由于从一种格式到另一种格式的转换总是相同的并且相当微不足道(虽然很长),我想我会在 superclass 中将它实现为一个具体的、密封的、静态的方法。
但是,后来我运行陷入了以下问题:
% (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()
是不可能的,因为需要使用 class 名称显式调用静态方法。也就是说,没有办法在上面的SuperClass.supersStaticMethod
中插入subclass名字来代替(???)
我尝试过的事情:
mfilename('class')
这行不通,因为这总是 returns 'SuperClass'
dbstack
不包含该方法实际上是从子class 调用的信息
我知道我可以通过使 supersStaticMethod
非静态并在临时实例(如 SubClass().supersStaticMethod()
)上调用该方法来解决这个问题。或者在每个 subclass 中创建一个小包装方法,它只调用 superclass 方法,并以 mfilename('class')
作为参数。或者其他 100 种看起来同样笨拙的东西中的任何一种。
但我真的很想知道是否有一些 meta.class
技巧或什么可以干净地解决这个问题。我所发现的只是 this dated thread,它以编程方式处理 MATLAB 命令行以获取 subclass 名称。
但是,我的 classes 将在 scripts/functions 中使用,命令行使用将仅用于调试目的...
有什么想法吗?
以下是我的骇人听闻的建议。思路是将当前调用class存储在SuperClass
的一个"static variable"中,然后查询该字段并在feval
中使用它来调用正确的subclass' 方法。几点说明:
- 它只能在你不进行一些并行计算的情况下工作(即在共享内存架构下一次从多个线程调用
SubClass#.supersStaticMethod
- 在这种情况下调用 class 字段将被不规律地覆盖)。
SuperClass
's supersStaticMethod
cannot be Sealed
, though the subclasses' 版本 可以.
- "static variable" 在
SubClass.supersStaticMethod
之后被清除,以确保此方法只被子class. 调用
- 出于演示目的,我已将
matlab.mixin.Heterogeneous
添加为 SuperClass
的超级 class。
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]
我有一大堆小的、相关的 class 通过接口 class 链接在一起。所有 classes 都实现了一个静态方法,该方法检索和处理特定于 class 的数据。
该静态方法的输出至少需要以两种方式进行格式化。由于从一种格式到另一种格式的转换总是相同的并且相当微不足道(虽然很长),我想我会在 superclass 中将它实现为一个具体的、密封的、静态的方法。
但是,后来我运行陷入了以下问题:
% (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()
是不可能的,因为需要使用 class 名称显式调用静态方法。也就是说,没有办法在上面的SuperClass.supersStaticMethod
中插入subclass名字来代替(???)
我尝试过的事情:
mfilename('class')
这行不通,因为这总是 returns'SuperClass'
dbstack
不包含该方法实际上是从子class 调用的信息
我知道我可以通过使 supersStaticMethod
非静态并在临时实例(如 SubClass().supersStaticMethod()
)上调用该方法来解决这个问题。或者在每个 subclass 中创建一个小包装方法,它只调用 superclass 方法,并以 mfilename('class')
作为参数。或者其他 100 种看起来同样笨拙的东西中的任何一种。
但我真的很想知道是否有一些 meta.class
技巧或什么可以干净地解决这个问题。我所发现的只是 this dated thread,它以编程方式处理 MATLAB 命令行以获取 subclass 名称。
但是,我的 classes 将在 scripts/functions 中使用,命令行使用将仅用于调试目的...
有什么想法吗?
以下是我的骇人听闻的建议。思路是将当前调用class存储在SuperClass
的一个"static variable"中,然后查询该字段并在feval
中使用它来调用正确的subclass' 方法。几点说明:
- 它只能在你不进行一些并行计算的情况下工作(即在共享内存架构下一次从多个线程调用
SubClass#.supersStaticMethod
- 在这种情况下调用 class 字段将被不规律地覆盖)。 SuperClass
'ssupersStaticMethod
cannot beSealed
, though the subclasses' 版本 可以.- "static variable" 在
SubClass.supersStaticMethod
之后被清除,以确保此方法只被子class. 调用
- 出于演示目的,我已将
matlab.mixin.Heterogeneous
添加为SuperClass
的超级 class。
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]