如何在自定义类中重载A{n}? matlab 2020a

问题描述 投票:0回答:1

背景知识

子引用

书中的一些解释(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 operator-overloading overloading overload-resolution matlab-class
1个回答
0
投票

您似乎正在讨论 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 的更多信息和示例,您可以参考此资源

© www.soinside.com 2019 - 2024. All rights reserved.