Как получить статические переменные-члены в классах MATLAB?
Есть ли способ определить статические переменные-члены в классах MATLAB?
Это не работает:
classdef A
properties ( Static )
m = 0;
end
end
Предлагается использовать ключевое слово "Constant" вместо "Static", свойства константы не могут быть изменены. Я хочу переменную, общую для всех объектов класса 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
Ответы
Ответ 1
Вы не можете, это по дизайну. Вы должны использовать переменную persistent
(технику из MATLAB в 1980 году, применяемую в 2011 году)!
Для полноты я должен упомянуть, что на самом деле существует с 2010b недокументированный и, возможно, не поддерживаемый модификатор свойства static
.
Для фона см. здесь ответ Дэйв Фоти, Менеджер группы MATLAB OO:
В MATLAB классы могут определять константу свойства, но не "статические" свойства в смысле других такие языки, как С++. Были бета-версии релизы, которые "Статические" свойства и недокументированный атрибут остается тогда. Однако атрибут Static недокументированные, не должны использоваться, и скорее всего, будут удалены в будущем Релиз MATLAB. R2008a реализует его как синоним Constant и обеспечивает нет дополнительной функциональности документированное поведение Constant свойства.
Постоянные свойства не могут быть изменены от начального значения, указанного в объявление собственности. Есть несколько причин, почему MATLAB работает как он это делает. Во-первых, MATLAB давние правила, что переменные всегда превалировать над именами функций и классов, и что присваивания переменная, если ее еще нет. Таким образом, любое выражение вида "A.B = C" вводит новую переменную A, являющуюся структурным массивом, содержащим поле B, значение которого равно C. Если "A.B = C" может относиться к статическому свойству класс А, тогда класс А прецедент над переменной A и этот будет очень значительным несовместимость с предыдущими выпусками MATLAB. Это означало бы, что m файл, содержащий задание утверждение "A.B = C" может иметь значение изменено введением класса A где-то на MATLAB путь. Программисты MATLAB имеют всегда можно было полагаться на назначение операторы, вводящие переменные тень любого другого использования с тем же именем.
Во-вторых, мы заметили, что статические данные редко используются в других классах за исключением частных данных в пределах класса или как общедоступные константы. Для Например, обзор нескольких Java библиотеки классов обнаружили, что все общедоступные статические поля также были окончательными. В MATLAB, константные свойства могут быть используется как "публичный конечный статический" полей в Java. Для внутренних данных класса, MATLAB уже имеет постоянные переменные, которые могут быть созданы внутри частных или защищенных методов или локальные функции, используемые класс. Есть также веские основания для избегать статических данных в MATLAB, где возможное. Если класс имеет статические данные, это может быть трудно использовать класс в нескольких приложениях потому что статические данные могут быть источником конфликтов среди Приложения. На некоторых других языках, это не проблема, потому что разные приложения отдельно скомпилирован в исполняемые файлы, запущенные в разные процессы с разными копии статических данных класса. В MATLAB, часто много разных приложения могут выполняться в тот же процесс и окружающая среда с единственная копия каждого класса.
Ответ 2
Вот прямой способ создания статического свойства в 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
>>
Ответ 3
(просто чтобы сообщить)
существует (другой?) способ создания статических данных в matlab
предположим, что у вас есть класс "handle", его имя - "автомобиль",
если вы хотите, чтобы класс автомобиля имел статические данные, вы могли бы построить другой класс дескриптора и использовать его в композиции броска класса автомобиля, последний класс работает как статические данные для класса автомобилей
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"
Ответ 4
Другим обходным решением, чтобы получить что-то вроде статических свойств, является использование того факта, что код инициализации для переменных-членов выполняется только один раз, когда загружается файл класса. Это означает, что если у вас есть определение типа
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
, который не является постоянным и может быть настроен на желание сердца.