2016-12-03 8 views
1

У меня есть класс, который инкапсулирует доступ к массиву в wierd способом; Конструктор класса принимает функцию ручку, которая является своим родом преобразования индексов перед передачей их в массивИмитировать 'this' указатель в matlab

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

Проблема анонимных функции копируют массив в его собственное рабочее пространство, и если мы изменяем массив, его не изменяется в функции. По существу то, что нужно, чтобы перейти к анонимной функции на «это» указатель/ссылку, как в Java/C++/и т.д.

Простое решение заключается в создании дескриптора массива и передать его функции:

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 

проблема теперь, когда я передать экземпляр класса к функции, ссылка передается по-прежнему относится к объекту за пределами функции:

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 

РЕДАКТИРОВАТЬ: Класс должен быть классом значений, семантика заключается в том, что при создании копии класса поле accessHandle изменяет обработчик массива, который он использует.

Как я могу достичь правильной семантики?

+2

Будет ли подклассификация 'handle' исправлена? – TroyHaskin

+0

@TroyHaskin @Suever Я не могу сделать это ручкой, как я объяснил в последнем отчёте; 'foo' не изменяет ввод, только его копия –

+0

Эквивалентное определение C++ для accessHandle будет' [this] (int x) {return this-> arr (trans (x));} ', если это помогает –

ответ

2

В настоящее время ваш класс является классом значений (по умолчанию MATLAB). Если вы хотите, чтобы иметь возможность передавать объекты вокруг по ссылке (изменения будут отражены в исходном объекте), вы будете сделать его handle class на подклассы 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 

И тогда вы можете использовать его так, как вам ожидаемый

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

m.accessHandle(2) 
% 2 

m.arr(2) = 5; 

m.accessHandle(2) 
% 5 

Дополнительная информация о разнице между двумя can be found here.

Редактировать

Если вам нужно MyClass быть классом значение, то вы можете сохранить значение 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 зависимым свойством, которое возвращает дескриптор функции.

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 
+0

См. Редактирование, класс должен быть классом значений, изменение относится только к определению 'accessHandle' –

+0

@OmerRosler Почему это должен быть класс ценности? Вы не можете этого сделать, не имея класс дескриптора. – Suever

+0

@OmerRosler Также почему вы не можете просто передать объект в анонимную функцию accessHandle? – Suever

 Смежные вопросы

  • Нет связанных вопросов^_^