Как получить статические переменные-члены в классах MATLAB? - PullRequest
15 голосов
/ 23 июня 2011

Есть ли способ определить статические переменные-члены в классах MATLAB?

Это не работает:

classdef A

    properties ( Static )
        m = 0;
    end
end

Предлагает использовать ключевое слово «Константа» вместо «Статический», свойства константы не могут быть изменены. Мне нужна переменная, общая для всех объектов класса A, и я хочу иметь возможность изменять эту переменную в методах класса A.

Итак, мне нужна закрытая статическая переменная-член. Есть ли способ получить его в MATLAB?


Обнаружено, что можно обойти эту проблему с использованием постоянных переменных в статических функциях-членах.

В этом случае вы должны наследовать все ваши классы от базового класса, как показано ниже.

classdef object < handle

    properties ( GetAccess = 'public', SetAccess = 'private' )
        id
    end

    methods ( Access = 'protected' )
        function obj = object()
            obj.id = object.increment();
        end
    end

    methods ( Static, Access = 'private' )
        function result = increment()
            persistent stamp;
            if isempty( stamp )
                stamp = 0;
            end
            stamp = stamp + uint32(1);
            result = stamp;
        end
    end  
end

Ответы [ 4 ]

15 голосов
/ 23 июня 2011

Нельзя, это по замыслу. Вам следует использовать переменную persistent (метод из MATLAB 1980 года, примененный в 2011 году)!

Для полноты следует отметить, что на самом деле на 2010b имеется недокументированный и, вероятно, больше не поддерживаемый static модификатор свойства.

Для справки см. здесь ответ Дейв Фоти , менеджер группы MATLAB OO:

В MATLAB классы могут определять константу свойства, но не "статические" свойства в смысле других такие языки, как C ++. Были бета релизы, которые экспериментировали с «Статические» свойства и недокументированный атрибут остается от затем. Тем не менее, статический атрибут без документов, не должны использоваться, и скорее всего, будут удалены в будущем MATLAB релиз. R2008a реализует это в качестве синонима константы и обеспечивает никаких дополнительных функций за пределами задокументированное поведение констант свойства.

Постоянные свойства не могут быть изменены от начального значения, указанного в декларация о недвижимости. Есть пара причин, почему MATLAB работает так оно и есть. Во-первых, MATLAB имеет давние правила, которые переменные всегда иметь прецедент над именами функций и классов и операторы присваивания вводят переменная, если она еще не существует. Таким образом, любое выражение вида "A.B = C "введет новую переменную A, которая является массивом структуры, содержащей поле B, значение которого равно C. Если «A.B = C» может ссылаться на статическое свойство класс А, то класс А будет принимать прецедент над переменной А и это было бы очень значительным несовместимость с предыдущими выпусками MATLAB. Это будет означать, что m-файл, содержащий назначение утверждение "A.B = C" может иметь значение изменено введением класса с именем A где-то на MATLAB путь. Программисты MATLAB имеют всегда был в состоянии положиться на задание заявления, вводящие переменные, которые скрывать любое другое использование того же имени.

Во-вторых, мы наблюдали, что статический данные редко используются в других классах кроме как частные данные в класс или как публичные константы. За Например, обзор нескольких Java библиотеки классов обнаружили, что все публичные статические поля также были окончательными. В MATLAB, постоянные свойства могут быть используется как "public final static" поля в Java. Для данных, внутренних к класс, MATLAB уже имеет постоянный переменные, которые могут быть созданы внутри частных или защищенных методов или локальные функции, используемые в частном порядке учебный класс. Есть также веские причины избегать статических данных в MATLAB, где возможный. Если класс имеет статические данные, может быть трудно использовать то же самое класс в нескольких приложениях потому что статические данные могут быть источник конфликтов между Приложения. На некоторых других языках это не проблема, потому что разные приложения по отдельности скомпилированы в исполняемые файлы, запущенные в разные процессы с разными копии статических данных класса. В MATLAB, часто много разных приложения могут быть запущены в тот же процесс и среда с один экземпляр каждого класса.

11 голосов
/ 29 января 2013

Вот прямой способ создать статическое свойство в Matlab.Единственная разница между этой реализацией и гипотетическим (но невозможным; см. Ответ Михаила) истинным статическим свойством заключается в синтаксисе для задания переменной-члена.

classdef StaticVarClass
    methods (Static = true)
        function val = staticVar(newval)
            persistent currentval;
            if nargin >= 1
                currentval = newval;
            end
            val = currentval;
        end
    end
end

Теперь статическое свойство staticVar можно прочитать через:

StaticVarClass.staticVar

... и устанавливается через:

StaticVarClass.staticVar(newval);

Так, например, это ожидаемый результат теста этой функциональности:

>> StaticVarClass.staticVar
  ans =
      []
>> StaticVarClass.staticVar('foobar')
  ans =
      foobar
>> StaticVarClass.staticVar
  ans =
      foobar
>> 

Этот подход работает так же хорошо для частных статических свойств, как вы просили, но демонстрационный код немного длиннее.Обратите внимание, что это не класс дескриптора (хотя он отлично работает и с классом дескриптора).

classdef StaticVarClass
    methods (Access = private, Static = true)
        function val = staticVar(newval)
            persistent currentval;
            if nargin >= 1
                currentval = newval;
            end
            val = currentval;
        end
    end

    methods
        function this = setStatic(this, newval)
            StaticVarClass.staticVar(newval);
        end

        function v = getStatic(this)
            v = StaticVarClass.staticVar;
        end
    end
end

... и тест:

>> x = StaticVarClass
  x = 
      StaticVarClass with no properties.
      Methods
>> x.getStatic
  ans =
      []
>> x.setStatic('foobar')
  ans = 
      StaticVarClass with no properties.
      Methods
>> x.getStatic
  ans =
      foobar
>> 
1 голос
/ 29 мая 2015

(просто для информирования) есть (еще один?) Способ создания статических данных в matlab

Предположим, что у вас есть класс "handle", имя которого - "car", если вы хотите автомобилькласс, чтобы иметь статические данные, вы могли бы создать другой класс дескриптора и использовать его в композиции броска класса автомобиля, последний класс работает как статические данные для класса автомобиля

classdef car<handle 
    properties 
         static_data:STATIC_DATA_HOLDER;
    end
end

classdef STATIC_DATA_HOLDER<handle
    properties
        data
    end
end

таким образом, когда вы создаете первый экземпляр классаВ классе автомобиля будет создан экземпляр STATIC_DATA_HOLDER, и при создании второго экземпляра класса автомобиля он использует ранее созданный класс STATIC_DATA_HOLDER.

этот код проверен с помощью "MATLAB 2013b"

0 голосов
/ 25 ноября 2015

Еще один обходной путь для получения чего-то похожего на статические свойства - это использование факта, что код инициализации для переменных-членов выполняется только один раз при загрузке файла класса.Это означает, что если у вас есть определение типа

classdef foo
    properties
        stuff = some_function()
    end
end

, то some_function вызывается только один раз, и если он возвращает объект типа класса, он будет использоваться всеми экземплярами.Я добавил пример реализации, который показывает, как это можно использовать:

classdef ClassWithStaticMembers
    properties
        classvars = StaticVarContainer('foo', 0, 'bar', 2);
        othervar
    end
    methods
        function obj=ClassWithStaticMembers(var)
            obj.othervar = var;
        end
    end 
end

classdef StaticVarContainer < dynamicprops
    methods
        function obj=StaticVarContainer(varargin)
            for i=1:2:numel(varargin)
                obj.addprop(varargin{i});
                obj.(varargin{i}) = varargin{i+1};
            end
        end
    end
end

Если вы запустите этот пример кода

obj1 = ClassWithStaticMembers(3);
obj2 = ClassWithStaticMembers(5);
obj1.classvars.foo = [2,3];

obj1.othervar
obj1.classvars

obj2.othervar
obj2.classvars

, вы увидите, что classvars действительнообщий.Я думаю, что это решение намного приятнее, чем использование постоянных переменных в функциях, поскольку вы можете использовать StaticVarContainer столько раз, сколько захотите, его проще использовать, и, кроме того, вы непосредственно видите инициализацию статических переменных в разделе свойств.

Чтобы получить результат, который требуется в вопросе OP (т. Е. Реализовать счетчик объектов), общее свойство может быть задано Constant, чтобы на него можно было ссылаться без экземпляра под рукой:

classdef ClassWithCounter
    properties (Constant)
        static = StaticVarContainer('counter', 0);
    end
    methods
        function obj=ClassWithCounter()
            obj.static.counter = obj.static.counter + 1;
        end
    end 
end

clear all
obj1 = ClassWithCounter();
obj2 = ClassWithCounter();
obj3 = ClassWithCounter();

ClassWithCounter.static.counter

Обратите внимание, что атрибут Constant означает только то, что, например, obj1.static нельзя изменить, но он не влияет на obj1.static.counter, который не является постоянным, и может быть установлен по желанию сердца.

...