Matlab类Set方法调用异常排查:基于cScenInsts类的测试分析
cScenInsts里Set方法调用时机异常的问题 先把你给出的cScenInsts类代码补全整理好(看你代码写到一半截断了,应该是有个set.TwinYrs方法对吧):
% @cScenInsts/cScenInsts.m classdef cScenInsts < matlab.mixin.Copyable properties TwinYrs = 5 % 默认值 end % properties methods function o = cScenInsts( TwinYrs_in ) % 构造函数 if exist('TwinYrs_in') && ~isempty( TwinYrs_in ) o.TwinYrs = TwinYrs_in ; else o.TwinYrs = o.TwinYrs ; end % if end % function cScenInsts() function o = set.TwinYrs(o, value) % 这应该是你定义的Set方法,用来校验输入 if isnumeric(value) && value > 0 o.TwinYrs = value; else error('TwinYrs必须是正数值'); end end end % methods end % classdef
结合你说的“Set方法调用时机不符合预期”,我梳理了几个Matlab类里最容易踩的坑,对应测试和解决办法:
1. 构造函数赋值时,Set方法被意外触发
Matlab默认规则:在构造函数里直接给属性赋值,会自动触发对应的Set方法。如果你本来以为构造函数里是直接初始化,不需要走校验逻辑,那肯定会觉得时机不对。
测试验证:
在set.TwinYrs方法开头加一行disp('Set方法被调用了!'),然后执行obj = cScenInsts(10),你会看到控制台打印出那句话——说明构造函数赋值时确实触发了Set方法。
解决办法:
如果想在构造函数里绕过Set方法直接赋值,用Matlab的父类属性赋值语法就行:
function o = cScenInsts( TwinYrs_in ) if exist('TwinYrs_in') && ~isempty( TwinYrs_in ) % 绕过Set方法,直接给属性赋值 o.TwinYrs@matlab.mixin.Copyable = TwinYrs_in; end end
2. 拷贝对象时,Set方法被意外触发
因为你的类继承了matlab.mixin.Copyable,当你调用copy(obj)复制对象时,Matlab会自动复制属性,这时候也可能触发Set方法——如果你的预期是拷贝只是原样复制,不需要走校验,这就会出问题。
测试验证:
创建对象obj = cScenInsts(5),然后执行obj2 = copy(obj),看Set方法有没有被调用。
解决办法:
重写copyElement方法,在拷贝时直接赋值属性,跳过Set方法:
methods(Access = protected) function o = copyElement(obj) o = copyElement@matlab.mixin.Copyable(obj); % 直接复制属性值,不触发Set方法 o.TwinYrs@matlab.mixin.Copyable = obj.TwinYrs; end end
3. 默认值初始化时,Set方法没被触发(不符合你的预期)
当你创建无参对象obj = cScenInsts时,Matlab会用默认值5初始化TwinYrs,但这个过程不会触发Set方法。如果你本来希望默认值也走一遍Set方法的校验逻辑,就会觉得时机不对。
测试验证:
创建无参对象,看Set方法有没有被调用——正常情况下是不会的。
解决办法:
在构造函数里显式调用Set方法来设置默认值:
function o = cScenInsts( TwinYrs_in ) if ~exist('TwinYrs_in') || isempty( TwinYrs_in ) % 显式调用Set方法设置默认值,确保校验逻辑生效 o = set.TwinYrs(o, 5); else o = set.TwinYrs(o, TwinYrs_in); end end
总结一下
你碰到的Set方法调用时机异常,基本上就是上面这三种场景之一。先对应测试一下是哪种情况,再用对应的解决办法调整就好。
内容的提问来源于stack exchange,提问作者user36800

