背景知识
书中的一些解释(2014年出版): 重载subsref方法时,可以使用switch语句来选择索引的类型并获取实际的索引值。以下三个代码片段说明了如何处理输入参数。在每种情况下,该函数都必须返回一个值,该值是索引的结果。 括号索引、运算 %括号索引,运算:A(n)
开关S型 案件 '()' B = A(S.subs{:}); 结束
大括号索引、操作
%Brace indexing, operation:A{n}
switch S.type
case '{}'
B = A.CellProperty{S.subs{:}}; %What is CellProperty????
end
会员索引、运营
%Member indexing, operation: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{:}}? 为了弄清楚这个问题,我在下面的示例代码中进行了实验,希望能够实现p{2}的重载。
示例代码 第34行是关键点
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 '()' %圆括号类型的引用 This is the key point You can set a program breakpoint here
ind = s.subs{:};
b = polyval(a.coef,ind); %返回多项式的值 This is the key point
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
接下来我将尝试实现P{2} 我希望 ans=29, 我将尝试修改示例代码的第 35 至 36 行 这种做法有一个错误;我无法添加断点 p=MPolynom([1,3,2,5]);无法执行
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 = a.{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}
程序在第 36 行抛出错误,“无法识别类“MPolynom”的方法、属性或字段“CellProperty”。
MPolynom/subsref 中的错误(第 36 行) ind = a.CellProperty{s.subs{:}};
那么,我们应该如何实现 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 = a.CellProperty{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
您似乎正在讨论 MATLAB 的 subsref 方法以及如何使用它来处理不同类型的索引。您提供的代码包括如何针对不同索引类型(例如括号、大括号和点符号)重载 subsref 方法的示例。
关于大括号索引(例如 p{2})的具体问题,需要注意的是,大括号索引 ({}) 通常用于 MATLAB 中的元胞数组,并且它期望对象具有名为 CellProperty 的属性或方法使用大括号索引检索元素。这就是您在未定义 CellProperty 属性或方法的情况下尝试使用 p{2} 时遇到错误的原因。
如果要实现 p{2} 的重载,则需要在 MPolynom 类中定义 CellProperty 属性或方法。以下是如何修改类以处理大括号索引的示例:
classdef MPolynom
properties
coef; % 多项式系数
end
methods
% ... (other methods and properties)
function value = subsref(obj, s)
switch s(1).type
case '()'
% Handle parentheses indexing
% ...
case '{}'
% Handle brace indexing
ind = s.subs{:};
% Implement logic to retrieve elements using brace indexing
% For example, you can access obj.coef as follows:
value = obj.coef{ind};
case '.'
% Handle dot notation
% ...
end
end
% ... (other methods)
end
end
在此修改后的类中,通过使用索引 ind 访问 obj.coef 属性来处理大括号索引 ({})。您可以自定义 subsref 方法内的逻辑,以满足您对大括号索引的特定需求。
有关使用 subsref 的更多信息和示例,您可以参考此资源。