Matlab 2020a中如何在自定义类中重载A{n}?
Matlab中subsref重载的疑问与解决方案
背景知识
Matlab重载subsref方法时,通常用switch语句区分索引类型并获取索引值,常见三种索引处理逻辑:
- 圆括号索引(
A(n))
switch S.type case '()' B = A(S.subs{:}); end
- 大括号索引(
A{n})
某2014年书籍中的示例代码如下,但其中的.CellProperty让人困惑:
%大括号索引操作:A{n} switch S.type case '{}' B = A.CellProperty{S.subs{:}}; %CellProperty是什么? end
- 成员索引(
A.name1)
%成员索引操作:A.name1 switch S.type case '.' switch S.subs case 'name1' B = A.name1; case 'name2' B = A.name2; end end
核心疑问:圆括号和成员索引的代码逻辑清晰,但大括号索引里的.CellProperty是什么?为什么不能直接写B = A{S.subs{:}}?
为验证问题,我基于多项式类MPolynom做实验,目标是实现p{2}的重载,期望返回多项式在x=2处的值(与p(2)结果一致,为29)。
基础可运行示例代码
以下代码已实现p(2)的功能,运行后能得到正确结果:
classdef MPolynom properties coef; %多项式系数 end methods function obj = MPolynom(c) %构造函数 if isa(c,'MPolynom') obj.coef = c.coef; else obj.coef = c(:)'; end end function plot(obj) %重载plot函数 r = max(abs(roots(obj.coef))); x = (-1.1:0.01:1.1)*r; y = polyval(obj.coef,x); plot(x,y); xlabel('X') ylabel('Y','Rotation',0) grid on end function r = plus(obj1,obj2) if ~isa(obj1,'MPolynom') %如果第一个参数不是类MPolynom对象 obj1 = MPolynom(obj1); %创建一个类MPolynom对象obj1 end if ~isa(obj2,'MPolynom') %如果第二个参数不是类MPolynom对象 obj2 = MPolynom(obj2); %创建一个类MPolynom对象obj2 end k = length(obj2.coef) - length(obj1.coef); %计算两个阵列的长度差 %创建一个类MPolynom对象作为返回值 r = MPolynom([zeros(1,k) obj1.coef]+[zeros(1,-k) obj2.coef]); end function b = subsref(a,s) %下标索引引用的实现 switch s(1).type case '()' %圆括号类型的引用 此处可设置断点 ind = s.subs{:}; b = polyval(a.coef,ind); %返回多项式的值 case '.' %“.”类型的引用 switch s(1).subs case 'coef' b = a.coef; case 'plot' %由于方法plot没有返回值,这里单独列出访问过程 a.plot; otherwise %其他带返回值方法的引用 if length(s)>1 b = a.(s(1).subs)(s(2).subs{:}); %带输入参数的方法引用 else b = a.(s.subs); %不带输入参数的方法引用 end end otherwise error('Specify value for x as obj(x)') end end function y = polyval(obj,x) %计算多项式对象obj在x处的值 y = polyval(obj.coef,x); end end end
运行测试代码:
p=MPolynom([1,3,2,5]); p(2) % 输出结果: % ans = % 29
错误尝试说明
尝试1:直接使用a.{s.subs{:}}
修改subsref中的大括号索引处理逻辑后,无法创建对象p=MPolynom([1,3,2,5]),也无法添加断点:
function b = subsref(a,s) %下标索引引用的实现 switch s(1).type case '{}' %大括号类型的引用 ind = a.{s.subs{:}}; % 语法错误,Matlab不支持这种写法 b = polyval(a.coef,ind); %返回多项式的值 % 其他代码不变 end end
尝试2:照搬书籍中的.CellProperty
这种方式能正常创建对象,但执行p{2}时会报错:Unrecognized method, property, or field 'CellProperty' of class 'MPolynom'
function b = subsref(a,s) %下标索引引用的实现 switch s(1).type case '{}' %大括号类型的引用 ind = a.CellProperty{s.subs{:}}; % 错误:MPolynom类未定义CellProperty属性 b = polyval(a.coef,ind); %返回多项式的值 % 其他代码不变 end end
正确实现p{2}重载的方法
书籍中的.CellProperty只是示例占位符,代表类中实际存在的单元格类型属性。对于MPolynom类,我们的目标是让p{2}返回多项式在x=2处的值,因此直接从s.subs中提取索引值即可,无需访问额外属性。
修改后的subsref方法如下:
function b = subsref(a,s) %下标索引引用的实现 switch s(1).type case '()' %圆括号类型的引用 ind = s.subs{:}; b = polyval(a.coef,ind); %返回多项式的值 case '{}' %大括号类型的引用 ind = s.subs{:}; % 直接获取大括号中的索引值 b = polyval(a.coef,ind); % 复用圆括号索引的计算逻辑 case '.' %“.”类型的引用 switch s(1).subs case 'coef' b = a.coef; case 'plot' %由于方法plot没有返回值,这里单独列出访问过程 a.plot; otherwise %其他带返回值方法的引用 if length(s)>1 b = a.(s(1).subs)(s(2).subs{:}); %带输入参数的方法引用 else b = a.(s.subs); %不带输入参数的方法引用 end end otherwise error('Specify value for x as obj(x) or obj{x}') end end
测试修改后的代码:
p=MPolynom([1,3,2,5]); p{2} % 输出结果: % ans = % 29
内容的提问来源于stack exchange,提问作者bokabokaboka
相关产品推荐
相关产品推荐

