在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
我有一个 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