Assuming a member within a class has private access properties, i.e., GetAccess=private, if we use a "." type reference for that member in the overloaded subsref method, then the access property of that member becomes invalid at that point.
--------------------- So, is there a good way here to allow users to both retain access control for properties and overload indexing methods?
Using the builtin function cannot resolve this issue; please alternate between the code at lines 42 and 43. The fundamental reason is that setting GetAccess=private cannot prevent access within the class itself. Therefore, the code at line 42 effectively provides a backdoor for accessing object, rendering the GetAccess restriction ineffective, and this is not caused by subsref. Even if you don't use subsref, if you construct an MPolynom object within the class and assign the data from object.coef to another property, for example, object.xxx=object.coef, and then assign object.xxx externally, it can bypass the GetAccess restriction. After all, it cannot prevent class methods from accessing any class members.
classdef MPolynom
properties (SetAccess=public,GetAccess=private)
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{:};
class(a.coef)
b = polyval(a.coef,ind); %返回多项式的值
case '.' %“.”类型的引用
switch s(1).subs
case 'coef'
b=builtin('subsref',a,s);
% b = a.coef;
case 'plot' %由于方法plot没有返回值,这里单独列出访问过程
a.plot;
otherwise %其他带返回值方法的引用
if length(s)>1
%b=subsref(a.coef,s);
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
Use the code on line 43 and comment out the code on line 42.
classdef MPolynom
properties (SetAccess=public,GetAccess=private)
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{:};
class(a.coef)
b = polyval(a.coef,ind); %返回多项式的值
case '.' %“.”类型的引用
switch s(1).subs
case 'coef'
% b=builtin('subsref',a,s);
b = a.coef;
case 'plot' %由于方法plot没有返回值,这里单独列出访问过程
a.plot;
otherwise %其他带返回值方法的引用
if length(s)>1
%b=subsref(a.coef,s);
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
Both of the above code snippets yield the same result when executing the following command. Therefore, the effective way to enforce the GetAccess restriction is to directly use error('GetAccess=private') at line 42.
p=MPolynom([1,3,2,5]);
p.coef
If you want to overload
()and/or{}indexing without affecting.indexing, you would start yoursubsreffunction with something like this:This simply calls the builtin (default) implementation of indexing if the first indexing operation is a
..Note that this takes care also of methods, such as
obj.plot. It is not necessary to manually implement that.Of corse you can also make this part of a standard
switchstatement:Reference: https://www.mathworks.com/help/matlab/matlab_oop/code-patterns-for-subsref-and-subsasgn-methods.html
It turns out that implementing the dot indexing in this way breaks access protection. The solution in MATLAB R2021b and later is described in the other answer. For earlier versions, the common solution is to manually filter the dot indexing:
Note also that from within class methods, indexing never calls the overloaded
subsreffunction. So the above will not affect your ability to access the 'coef' property inside class methods.