0

Background knowledge

subsref

Some explanations in the book (published in 2014): When overloading the subsref method, you can use a switch statement to select the type of index and obtain the actual index value. The following three code snippets illustrate how to handle the input parameters. In each case, the function must return a value, which is the result of the indexing. Parentheses indexing, operation %Parentheses indexing, operation:A(n)

switch S.type case '()' B = A(S.subs{:}); end

Brace indexing, operation

%Brace indexing, operation:A{n}
switch S.type
    case '{}'
       B = A.CellProperty{S.subs{:}};    %What is CellProperty????
end

Member indexing, operation

%Member indexing, operation:A.name1
    switch S.type
    case '.'
       switch S.subs
       case 'name1'
          B = A.name1;
       case 'name2'
          B = A.name2;
       end
    end

The other two pieces of code are easy to understand, but Brace indexing is a bit confusing. What is .CellProperty? Why can't we use B = A{S.subs{:}}? To clarify this issue, I conducted an experiment in the following example code, hoping to achieve an overload for p{2}.


Example Code line34 is key point

    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

Running the following code will yield the correct result

p=MPolynom([1,3,2,5]);
p(2)
ans =
    29

Next, I will attempt to implement P{2} I wish ans=29, I will try modifying lines 35 to 36 of the Example Code This approach has an error; I cannot add breakpoints p=MPolynom([1,3,2,5]); cannot be executed

 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

Another approach p=MPolynom([1,3,2,5]); can be executed But when executing p{2}
the program throws an error at line 36, 'Unrecognized method, property, or field 'CellProperty' of class 'MPolynom'. Error in MPolynom/subsref (line 36) ind = a.CellProperty{s.subs{:}};

So, how should we implement an overload for 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

2 Answers2

0

It seems you're discussing MATLAB's subsref method and how it can be used to handle different types of indexing. The code you provided includes examples of how to overload the subsref method for different indexing types, such as parentheses, braces, and dot notation.

Regarding the specific issue with brace indexing (e.g., p{2}), it's important to note that brace indexing ({}) is typically used for cell arrays in MATLAB, and it expects the object to have a property or method called CellProperty to retrieve elements using brace indexing. This is why you encountered an error when trying to use p{2} without a CellProperty property or method defined.

If you want to implement an overload for p{2}, you would need to define the CellProperty property or method in your class MPolynom. Here's an example of how you can modify your class to handle brace indexing:

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

In this modified class, brace indexing ({}) is handled by accessing the obj.coef property using the index ind. You can customize the logic inside the subsref method to suit your specific needs for brace indexing.

For more information and examples on using subsref, you can refer to this resource.

XCFzLoc
  • 19
  • 1
  • This is something that’s also wrong in OP’s code, you probably just copy-pasted it from there, but `ind = s.subs{:}` will fail if there is more than one index. Also, `obj.coef{ind}` should read `obj.coef(ind)` because it’s a numeric array, not a cell array. – Cris Luengo Sep 02 '23 at 16:08
0

Although I'm still not entirely clear about the meaning of the following code segment (I feel like it's misleading), I have successfully modified lines 35 and 36 of the Example Code to achieve overloading of {}.

%Brace indexing, operation:A{n}
switch S.type
    case '{}'
       B = A.CellProperty{S.subs{:}};    %What is CellProperty????
end

The modified Example Code

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

The execution result

p=MPolynom([1,3,2,5]);
p{2}
ans =

    29