6

特定のクラスの subsref 呼び出しの 1 つのタイプ (「()」タイプ) のみをオーバーロードし、Matlab の組み込みの subsref への他の呼び出しを残します。具体的には、Matlab に '. ' タイプ。しかし、クラスで subsref がオー​​バーロードされていると、Matlab の「組み込み」関数が機能しないようです。

このクラスを考えてみましょう:

classdef TestBuiltIn
    properties
        testprop = 'This is the built in method';
    end

    methods
        function v = subsref(this, s)
            disp('This is the overloaded method');
        end
    end
end

オーバーロードされた subsref メソッドを使用するには、次のようにします。

t = TestBuiltIn;
t.testprop
    >> This is the overloaded method

それは予想通りです。しかし今、Matlab の組み込みの subsref メソッドを呼び出したいと思います。正しく動作していることを確認するために、最初に構造体で同様の呼び出しを試します。

x.testprop = 'Accessed correctly';
s.type = '.';
s.subs = 'testprop';
builtin('subsref', x, s)
    >> Accessed correctly

それも予想通り。しかし、TestBuiltIn で同じ方法を試すと、次のようになります。

builtin('subsref', t, s)
    >> This is the overloaded method

...Matlab は、組み込みメソッドではなく、オーバーロードされたメソッドを呼び出します。組み込みメソッドを呼び出すように要求したときに、Matlab がオーバーロードされたメソッドを呼び出すのはなぜですか?

更新: @Andrew Janke の回答に応えて、その解決策はほとんど機能しますが、完全には機能しません。このクラスを考えてみましょう:

classdef TestIndexing
    properties
        prop1
        child
    end

    methods
        function this = TestIndexing(n)
            if nargin==0
                n = 1;
            end

            this.prop1 = n;
            if n<2
                this.child = TestIndexing(n+1);
            else
                this.child = ['child on instance ' num2str(n)];
            end
        end

        function v = subsref(this, s)
            if strcmp(s(1).type, '()')
                v = 'overloaded method';
            else
                v = builtin('subsref', this, s);
            end
        end
    end
end

これはすべて機能します:

t = TestIndexing;
t(1)
    >> overloaded method
t.prop1
    >> 1
t.child
    >> [TestIndexing instance]
t.child.prop1
    >> 2

しかし、これはうまくいきません。オーバーロードされた subsref ではなく、子に対して組み込みの subsref を使用します。

t.child(1)
    >> [TestIndexing instance]

上記の動作は、これらの動作の両方と一致しないことに注意してください (これは予想どおりです)。

tc = t.child;
tc(1)
    >> overloaded method

x.child = t.child;
x.child(1)
    >> overloaded method
4

4 に答える 4

4

可能です、IIRC。'.' では()なく変更するには、組み込みを外部から明示的に呼び出そうとするのではなく、オーバーロードされた subsref 内からこれらの他のケースを組み込み subsref に渡すメソッドを記述します。{}subsref

function B = subsref(A, S)
    % Handle the first indexing on your obj itself
    switch S(1).type
        case '()'
            B = % ... do your custom "()" behavior ...
        otherwise
            % Enable normal "." and "{}" behavior
            B = builtin('subsref', A, S(1))
        end
    end
    % Handle "chaining" (not sure this part is fully correct; it is tricky)
    orig_B = B; % hold on to a copy for debugging purposes
    if numel(S) > 1
        B = subsref(B, S(2:end)); % regular call, not "builtin", to support overrides
    end
end

(そして、そのbuiltin呼び出しが機能しない場合は、オーバーロードがクラス定義内で無視されるため、 .and を{}直接使用するケースを入れることができます。)subsref

完全に機能させるには、B を varargout に変更し、「()」ケースに連鎖動作を追加する必要がある場合があります。

于 2013-04-24T20:40:14.977 に答える
0

この問題の更新版では、 を呼び出すt.child(1)と、関数はと で引数をsubsref受け取ります。Andrew Jankeが回答で述べたように、この式の評価は段階的な方法ではありません。その結果、 をオーバーライドするときは、最初に「.」を処理して、この操作チェーンを処理する必要があります。オペレーター。これはあなたのケースの不完全な例です。ss(1).type='.', s(1).subs='child's(2).type='()', s(2).subs='1'subsref

function v = subsref(this, s)
    switch s(1).type
       case '.'
           member = s(1).subs;
           if ismethod(this, member)
               % invoke builtin function to access method member
               % there is issue about the number of output arguments
               v = builtin('subsref',this,s);
           elseif isprop(this, member) % property
               if length(s) == 1
                   % invoke builtin function to access method member
                   v = builtin('subsref', this, s);
               elseif length(s) == 2 && strcmp(s(2).type,'()')
                   % this is where you evaluate 'tc.child(1)'
               else
                   % add other cases when you need, otherwise calling builtin
               end
           else
               % handling error.
           end
       case '()'
           % this is where you evaluate 't(1)'
           % you may need to handle something like 't(1).prop1', like the '.' case
       otherwise
           % by default, calling the builtin.
    end
end

subsref メソッドと subsasgn メソッドのコード パターンで、詳細なコード サンプルと手順を見つけることもできます。

もう 1 つ知っておく必要があることは、このクラスのメソッド メンバーsubsrefも「.」を使用して呼び出されるということです。手術。クラスに関するこのサブジェクトsubsref を見てください: メソッドをディスパッチする方法? builtin関数に戻り値がないことがわかります(呼び出されたメソッドには戻り値がないため)。ただし、 の戻り値builtinは に代入されvます (vは に置き換えられますがvarargout)。これは明らかなエラーです。作者はまた、try ... catchこのエラーを解決するために を使用して一時的な解決策を提供します。

于 2017-08-03T02:21:44.133 に答える
0

一般に。builtin(m,s)オーバーロードされた関数内で使用する必要があります。これは、MATLAB ドキュメントで明確に指定されています。

http://www.mathworks.com/help/matlab/ref/builtin.html

builtin(function,x1,...,xn) は、入力引数 x1 から xn を使用して組み込み関数を実行します。関数をオーバーロードするメソッド内から元の組み込みを実行するには、builtin を使用します。正しく動作するためには、ビルトインをオーバーロードしてはなりません。

次のコードを検討してください。

classdef TestBuiltIn
    properties
        testprop = 'This is the built in method';
        testprop2 = 'This is the derived subsref ';
    end
    methods

        function v = subsref(m, s)
            disp('enter subsref no matter how!');
            v = builtin('subsref',m, s);
        end
    end
end

およびテストコマンド

clear;
t = TestBuiltIn;
builtin('subsref', t, s)
s.type = '.';
s.subs = 'testprop';
s2 = s;
s2.subs = 'testprop2';

>> builtin('subsref', t, s1)

enter subsref no matter how!

ans =

This is the derived subsref 

>> builtin('subsref', t, s)
enter subsref no matter how!

ans =

This is the built in method
于 2013-04-24T20:49:44.100 に答える