在matlab中模拟'this'指针

Simulate 'this' pointer in matlab

我有一个 class 以一种奇怪的方式封装了对数组的访问; class 构造函数接受一个函数句柄,它是在将索引传递给数组之前对索引进行某种转换

classdef MyClass
properties
    arr
    accessHandle
end
methods
function obj = MyClass(array, trans)
    obj.arr = array;
    obj.accessHandle = @(i) obj.arr(trans(i))
end
end

问题是匿名函数将数组复制到它自己的工作区中,如果我们更改数组,它不会在函数中更改。 本质上需要的是将 'this' pointer/reference 传递给匿名函数,如 Java/C++/etc

简单的解决方案是创建数组句柄并将其传递给函数:

classdef MyClass
properties
    arr
    accessHandle
end
methods
function obj = MyClass(array, trans)
    obj.arr = array;
    tmp = PropertyReference(obj, 'arr'); %See  
    %for the definition
    obj.accessHandle = @(i) tmp(trans(i));
end
end
end

现在的问题是,当我将 class 的实例传递给函数时,传递的引用仍然引用函数外部的对象:

function foo(ins)
    ins.arr = [1 2];
    disp(ins.accessHandle(1));
end
cl = MyClass([0 3], @(x) x);
foo(cl) //output 0 instead of 1
disp(ins.accessHandle(1)) //output 0

编辑: class 应该是一个值 class,语义是当制作 class 的副本时, accessHandle 字段更改它使用的数组句柄。

如何实现正确的语义?

目前,您的 class 是一个值 class(MATLAB 的默认值)。如果您希望能够通过引用传递对象(更改将反映在原始对象中),您将通过 subclassing handle [= 使其成为 handle class 20=]

classdef MyClass < handle
    properties
        arr
        accessHandle
    end

    methods
        function obj = MyClass(array, trans)
            obj.arr = array;
            obj.accessHandle = @(i) obj.arr(trans(i))
        end
    end
end

然后你就可以按照你期望的方式使用它了

m = MyClass([1 2 3], @(x)x);

m.accessHandle(2)
%   2

m.arr(2) = 5;

m.accessHandle(2)
%   5

关于两者区别的更多信息can be found here

编辑

如果您需要 MyClass 成为值 class,那么您可以将 trans 值存储为 属性,然后使用正常方法访问值

classdef MyClass
    properties
        arr
        trans
    end

    methods
        function obj = MyClass(array, trans)
            obj.arr = array;
            obj.trans = trans;
        end

        function res = access(obj, k)
            res = obj.arr(obj.trans(k));
        end
    end
end

或者,如果您愿意,可以使 accessHandle 成为从属 属性,returns 成为函数句柄。

classdef MyClass
    properties
        arr
        trans
    end

    properties (Dependent)
        accessHandle
    end

    methods
        function obj = MyClass(array, trans)
            obj.arr = array;
            obj.trans = trans;
        end

        function res = get.accessHandle(obj)
            res = @(i)obj.arr(obj.trans(i));
        end
    end
end