Search code examples
matlabthisfunction-handle

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 ?


Solution

  • 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