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

Есть ли способ определить статические переменные-члены в классах 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

person Vahagn    schedule 23.06.2011    source источник
comment
это не предназначено для этого, насколько я знаю, но работает ли persistent?   -  person Tobias Kienzler    schedule 23.06.2011
comment
Да, я нашел обходной путь с постоянной переменной в статической функции-члене.   -  person Vahagn    schedule 23.06.2011
comment
вы должны опубликовать его как ответ для других, заинтересованных в этом вопросе   -  person Tobias Kienzler    schedule 23.06.2011
comment
persistent не будет выделяться отдельно для подклассов   -  person Eric    schedule 14.03.2017


Ответы (4)


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

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

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

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

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

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

person Mikhail    schedule 23.06.2011
comment
К сожалению, ссылка "здесь" не работает :( - person Rick Moritz; 24.11.2018

Вот прямой способ создать статическое свойство в 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
>> 
person Ben    schedule 28.01.2013

(просто сообщить) есть (другой?) способ создания статических данных в Matlab

предположим, что у вас есть класс «дескриптор», имя которого «автомобиль», если вы хотите, чтобы класс автомобиля имел статические данные, вы можете создать другой класс дескриптора и использовать его в композиции броска класса автомобиля, последний класс работает как статические данные для класса автомобиля

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"

person Hadi    schedule 29.05.2015
comment
спасибо, а в качестве дополнительного совета посмотрите здесь: mathworks.com/help/matlab /matlab_oop/static-data.html - person Seyfi; 10.09.2018

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

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, который непостоянен и может быть установлен по желанию.

person Elmar Zander    schedule 25.11.2015