Omer Rosler
Omer Rosler

Reputation: 247

Simulate 'this' pointer in matlab

I have a class that encapsulates access to an array in a wierd way; The class constructor takes a function handle which is some kind of transformation of indexes before passing them to the array

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

The problem is the anonymous function copies the array into it's own workspace and if we change the array, it doesn't change in the function. Essentially what is needed is to pass to the anonymous function the 'this' pointer/reference like in Java/C++/etc

The simple solution is to create a handle to the array and pass it along to the function:

classdef MyClass
properties
    arr
    accessHandle
end
methods
function obj = MyClass(array, trans)
    obj.arr = array;
    tmp = PropertyReference(obj, 'arr'); %See http://stackoverflow.com/questions/7085588/matlab-create-reference-handle-to-variable 
    %for the definition
    obj.accessHandle = @(i) tmp(trans(i));
end
end
end

The problem now is when I pass an instance of the class to a function, the reference passed still refers to the object outside the function:

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

EDIT: The class should be a value class, the semantics are that when a copy of the class is made, the accessHandle field changes the array handle it uses.

How can I achieve the right semantics ?

Upvotes: 1

Views: 808

Answers (1)

Suever
Suever

Reputation: 65460

Currently, your class is a value class (MATLAB's default). If you want to be able to pass objects around by reference (changes will be reflected in the original object), you'll to make it a handle class by subclassing handle

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

And then you can use it the way you expect

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

m.accessHandle(2)
%   2

m.arr(2) = 5;

m.accessHandle(2)
%   5

More information about the difference between the two can be found here.

Edit

If you need MyClass to be a value class, then you could store the trans value as a property and then have a normal method to access the value

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

Or if you want, you could make accessHandle a dependent property that returns a function handle.

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

Upvotes: 2

Related Questions