提问人:skm 提问时间:10/12/2023 最后编辑:Cris Luengoskm 更新时间:10/13/2023 访问量:60
需要类通过句柄公开私有静态函数
Need class to expose a private static function via handle
问:
我需要一个特定的类来公开一个私有的静态函数。我通过存储在元胞数组中的匿名函数来执行此操作。下面人为的例子说明了这个问题:
classdef ParamClass
properties (Constant)
param_spec = {
{'param_1', @(x) isnumeric(x) && isscalar(x) && (x > 0)}, ...
{'param_2', @(x) ParamClass.validate_param_2(x)} ...
};
end
properties
param_1;
param_2;
end
methods (Static, Access = 'private')
function ok = validate_param_2(x)
ok = isnumeric(x) && isscalar(x) && (x < 0);
end
end
methods
function obj = ParamClass(p1, p2)
opts = parse_my_args(p1, p2, ParamClass.param_spec{:});
obj.param_1 = opts.param_1;
obj.param_2 = opts.param_2;
end
end
end
function opts = parse_my_args(p1, p2, varargin)
assert(varargin{1}{2}(p1));
assert(varargin{2}{2}(p2));
opts.param_1 = p1;
opts.param_2 = p2;
end
该函数是私有静态的,但我希望它由外部独立函数通过匿名函数包装器调用。但是,我收到以下错误:ParamClass.validate_param_2
使用ParamClass.validate_param_2时出错
无法访问类“ParamClass”中的方法“validate_param_2”。
经过一番思考,这个错误似乎没有必要。该类将函数句柄传递给外部。句柄的内容应该只由班级决定,不应该是任何人的事。难道不应该所有必需的上下文都是匿名函数的一部分吗?当然,我可以通过公开来消除错误,但我想了解错误背后的基本原理。validate_param_2
validate_param_2
任何解释为什么需要这种错误的评论将不胜感激。还有其他选择吗?
答:
0赞
Cris Luengo
10/13/2023
#1
这确实是一个奇怪的错误,我认为这没有多大意义。一种解释可能是,在计算属性约束时,类定义在内存中尚未完成,并且函数尚不可用。但同样,没有理由这样做,它可能不是一个有意识的选择(即这是一个错误)。ParamClass.validate_param_2()
作为替代方案,您可以改用本地函数(即在同一文件中在块之后定义的函数)。这样的函数仅在文件中可见,但您可以返回它的句柄,使其可在另一个文件中使用。此本地函数还可以访问类的私有成员。就所有意图和目的而言,它都是一个私有成员,只是它只能在文件中可见 - 目录中定义的类方法将无法看到它。classdef
@ParamClass
classdef ParamClass
properties (Constant)
param_spec = {
{'param_1', @(x) isnumeric(x) && isscalar(x) && (x > 0)}, ...
{'param_2', @validate_param_2} ...
};
end
properties
param_1;
param_2;
end
methods
function obj = ParamClass(p1, p2)
opts = parse_my_args(p1, p2, ParamClass.param_spec{:});
obj.param_1 = opts.param_1;
obj.param_2 = opts.param_2;
end
end
end
function opts = parse_my_args(p1, p2, varargin)
assert(varargin{1}{2}(p1));
assert(varargin{2}{2}(p2));
opts.param_1 = p1;
opts.param_2 = p2;
end
function ok = validate_param_2(x)
ok = isnumeric(x) && isscalar(x) && (x < 0);
end
评论
0赞
skm
10/13/2023
谢谢。这或多或少解决了问题。另一个问题,与确切的问题没有直接关系,我昨天没有注意到,在我的示例代码中,为了方便起见,我将函数 parse_my_args“ 放在类文件中。然而,尽管在类文件中,Matlab 不允许它通过元胞数组访问类私有静态“validate_param_2”,这从错误中可以明显看出。
0赞
skm
10/13/2023
好的,很抱歉继续这个,但是在您发布的修改后的代码中,您已将@(x) ParamClass.validate_param_2(x)替换为@validate_param_2。后者有效,但前者不起作用,matlab 给出错误(发生在 parse_my_args 函数中)“无法识别的函数或变量'validate_param_2”。不幸的是,在原始代码中,我需要匿名包装器,因为还涉及其他变量。
0赞
Cris Luengo
10/13/2023
@skm 回复您的第二条评论:使用 .从技术上讲,它不是 的成员,因此无效。回复您的第一条评论:我不确定您在这里问什么。“从错误中可以明显看出。”什么错误?您如何尝试访问该类私有静态函数,什么是“通过元胞数组”?@(x) validate_param_2(x)
ParamClass
ParamClass.validate_param_2
0赞
skm
10/13/2023
一旦我把validate_param_2带到类之外并把它变成一个本地函数,我就通过元胞数组访问它,该数组现在包含匿名函数@(x) validate_param_2(x)(注意:没有类命名空间 - 第二条评论中有一个错别字)。但是我收到错误“无法识别的函数或变量'validate_param_2”。
0赞
skm
10/13/2023
关于我的第一条评论,我的意思是,如果“parse_my_args”在类文件中,并且 Matlab 允许类文件本地函数访问私有类成员,那么理论上,原始帖子中的初始问题应该永远不会发生。
评论