Инициализация свойства в MATLAB - PullRequest
0 голосов
/ 15 сентября 2018

В MATLAB есть два способа инициализировать его свойства. Либо прямо в свойствах:

classdef A
    properties
       foo = 'bar';
    end
end

или явно указав конструктор:

classdef B
    properties
        foo;
    end

    methods this = B()
        this.foo = 'bar';
    end
end

Какой способ предпочтительнее?

(я спрашиваю, потому что есть аналогичный случай в C ++, где предпочтительным способом является инициализация переменных-членов двоеточием после конструктора, а не присваивание переменных внутри конструктора).

Ответы [ 2 ]

0 голосов
/ 17 сентября 2018

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

Но они не одинаковы, и в некоторых случаях вы попадете в беду, если не будете знать о различиях.

Существенным отличием является то, что свойства, которые инициализируются в конструкторе, инициализируются отдельно при каждом построении объекта, тогда как свойства, которые инициализируются в блоке свойств значением по умолчанию, инициализируются один раз, когда определение класса впервые читается. Значением по умолчанию в блоке свойств является значение по умолчанию class , а не объекта; и (используя отражение) вы можете запросить это значение по умолчанию, даже если ни один экземпляр класса еще не был создан.

В большинстве случаев это не имеет значения - но когда начальное значение является объектом-дескриптором или выводом неопределенной функции, это делает. Итак, рассмотрим следующие два класса:

classdef A
    properties
        foo
    end
    methods
        function obj = A
            obj.foo = containers.Map;
        end
    end
end

classdef B
    properties
        foo = containers.Map
    end
end

Обратите внимание, что containers.Map является классом дескриптора.

В классе A каждый раз, когда вы создаете новый экземпляр A, вы получаете новый / другой containers.Map для его foo. В B каждый экземпляр B получает одинаковые containers.Map для своих foo, поскольку свойство инициализируется только один раз, при первом чтении определения класса. Поэтому, если вы измените foo для любого объекта класса B, это изменение распространяется на все другие экземпляры класса B, как вы можете видеть:

>> a1 = A; a2 = A; a1.foo('greeting') = 'hello'; a2.foo('greeting') = 'bonjour';
>> a1.foo('greeting'), a2.foo('greeting')
ans =
    'hello'
ans =
    'bonjour'
>> b1 = B; b2 = B; b1.foo('greeting') = 'hello'; b2.foo('greeting') = 'bonjour';
>> b1.foo('greeting'), b2.foo('greeting')
ans =
    'bonjour'
ans =
    'bonjour'
>> % Note that b1.foo has changed as a result of setting b2.foo

Этот пункт о классах обработки, так как значения по умолчанию часто сбивают людей с толку; но поведение не специфично для обработки классов. Например, рассмотрим следующий вариант:

classdef A
    properties
        foo
    end
    methods
        function obj = A
            obj.foo = datetime('now');
        end
    end
end

classdef B
    properties
        foo = datetime('now')
    end
end

Здесь A будет хранить время создания каждого объекта, тогда как B будет хранить время, когда класс был впервые инициализирован, для всех объектов, независимо от того, когда они были созданы.

Если вы считаете, что это поведение сбивает с толку, см. https://undocumentedmatlab.com/blog/handle-object-as-default-class-property-value, и, в частности, ветку комментариев под этой статьей, для обсуждения проблемы и объяснения причин, по которым MATLAB разработан таким образом.


Редактировать: Замечательный вопрос в комментариях, касающийся поведения clear и его отношения к этой проблеме.

Используя вторую реализацию классов выше (с datetime), посмотрите на следующее:

>> a = A; b = B; datestr(a.foo), datestr(b.foo)
ans =
    '01-Sep-2018 18:59:30'
ans =
    '01-Sep-2018 18:59:30'
>> clear variables
>> a = A; b = B; datestr(a.foo), datestr(b.foo)
ans =
    '01-Sep-2018 18:59:48'
ans =
    '01-Sep-2018 18:59:30'
>> clear classes
>> a = A; b = B; datestr(a.foo), datestr(b.foo)
ans =
    '01-Sep-2018 18:59:57'
ans =
    '01-Sep-2018 18:59:57'

Итак, прежде всего мы создаем A и B и отображаем их foo s, и они оба показывают одинаковое время. Затем мы немного подождем, сделаем clear variables и сделаем это снова. Обратите внимание, что foo с A - это новое время, а foo с B остается таким же, как и раньше. Наконец, мы ждем немного больше времени, мы делаем clear classes, и мы делаем это снова. На этот раз у A и B есть новое время.

Почему? Потому что clear variables просто удаляет ссылки на переменные из рабочей области. Определение класса B не очищается, поэтому, когда мы создаем еще один B, он по-прежнему использует значение с момента, когда определение класса было впервые прочитано. clear classes, напротив, также удаляет определение класса , поэтому, когда мы позже создаем новый B, он получает это время, поскольку определение класса затем перечитывается. Все это не имеет отношения к A, поскольку foo только что дали значение во время строительства.

Обратите внимание, что clear classes очищает все определения классов: вы можете очистить определение только класса B, используя clear B.

0 голосов
/ 16 сентября 2018

Это на ваше усмотрение, за исключением некоторых случаев.

Позвольте мне упомянуть, когда мы используем двоеточие в Constructor function в C++:

1- Вызов базового классаКонструкторы

2- Инициализация переменных-членов перед выполнением тела конструктора.

No. # 1 также может использоваться в теле, но мы должны использовать двоеточие в No. #2, когда членом является const.

НО

Но здесь есть Matlab с его собственным синтаксисом и структурой языка.

Используйте тот, который делает вашу работу.

Но здесь, в Matlab, когда вы хотите определить Constant свойства, вы ДОЛЖНЫ определить его в properties части, и вы не можете сделать это в функции инициализатора / конструктора.

classdef NamedConst
   properties (Constant)
      R = pi/180; % Can't define it in constructor body, because it is `Constant properties`
  end
  %class body
end
Добро пожаловать на сайт PullRequest, где вы можете задавать вопросы и получать ответы от других членов сообщества.
...