Как мне установить по умолчанию свойство экземпляра Matlab с размером, основанным на переменной экземпляра, которая устанавливается при создании экземпляра? - PullRequest
1 голос
/ 23 октября 2019

У меня есть проблема, в которой я хочу смоделировать какое-то физическое явление. Это явление состоит из нескольких фаз, каждая из которых может иметь свои собственные определяющие уравнения (динамика и, следовательно, количество переменных, ограничений, границ переменных и т. Д.). Чтобы сгруппировать свойства этой фазы, я написал класс phase. Экземпляр этого класса имеет, ао, свойство, называемое nVars, числом переменных в определяющих уравнениях (которое, таким образом, может варьироваться в зависимости от экземпляров этого класса).

Теперь предположим, что я хочу иметь другое свойство для этого класса, которое называется boundaries. Поскольку мне требуется, чтобы границы переменных были сформулированы очень специфическим образом, я также создаю класс boundaries. Этот класс имеет свойства lower и upper;нижняя и верхняя границы переменных. Однако длина этих нижних и верхних границ зависит от nVars экземпляра phase.

В самом общем случае все нижние границы -Inf, а верхние - Inf. Поэтому я хочу установить значения свойств boundaries lower и upper по умолчанию -Inf * ones([1 nVars]) и Inf * ones([1 nVars]) соответственно. Теперь мой вопрос: как сделать значение свойства класса по умолчанию зависимым от переменной (nVars в данном случае).

Моя первая попытка:

classdef phase
    properties 
        nVars(1, 1) double
        boundaries boundaries
    end
    methods
        function obj = phase(nVars)
            %Some constructor method
            obj.nVars = nVars;
            obj.boundaries = boundaries(obj);
        end
    end
end

classdef boundaries
    properties 
        parent phase
        lower = -Inf * ones([1 parent.nVars]);
        upper = Inf * ones([1 parent.nVars]);
    end
    methods
        function obj = boundaries(parent)
            %Some constructor method
            obj.parent = parent;
        end
    end
end

В качестве альтернативыЯ попытался установить значения по умолчанию для свойств класса границ следующим образом:

classdef boundaries
    properties 
        parent phase
        lower(1, parent.nVars) double = -Inf;
        upper(1, parent.nVars) double = Inf;
    end
    methods
        function obj = boundaries(parent)
            %Some constructor method
            obj.parent = parent;
        end
    end
end

Может кто-нибудь помочь мне понять, как присваивать эти значения по умолчанию на основе переменной?

1 Ответ

0 голосов
/ 23 октября 2019
classdef phase < handle
    properties 
        nVars       double ;
        boundaries  boundaries ;
    end
    methods
        function obj = phase(nVars)
            %Some constructor method
            obj.nVars = nVars;
            obj.boundaries = boundaries(obj);
        end
    end
end

classdef boundaries
    properties 
        parent phase
        upper   double ;
        lower   double ;
    end
    methods
        function obj = boundaries( parent )
            % Assign the parent handle
            obj.parent = parent ;
            % Initialise default values for the properties
            obj.upper =  Inf * ones([1 parent.nVars]);
            obj.lower = -obj.upper ;
        end
    end
end

Это правильно инициализируется:

>> a = phase(5)
a = 
  phase with properties:

         nVars: 5
    boundaries: [1x1 boundaries]
>> a.boundaries
ans = 
  boundaries with properties:

    parent: [1x1 phase]
     upper: [Inf Inf Inf Inf Inf]
     lower: [-Inf -Inf -Inf -Inf -Inf]

Синтаксис classdef, который позволяет задавать значения по умолчанию в свойствах, что удобно для ограничения усилий по кодированию, которые должны выполняться в конструкторе. (автоматическая проверка типа ввода и все виды проверки ввода).

Однако для каждого значения по умолчанию, которое вы определяете в блоке свойств, под капотом MATLAB добавьте автоматически сгенерированный код в конструктор объекта. Как только объект наконец создан и инициализирован, он делает без разницы , если значения свойства были назначены непосредственно в блоке свойств или в конструкторе.

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

Когда вы пытаетесь присвоить дескриптор родительскому объекту в вашем классе boundaries, вы просто отправляете копия вашего начального фазового объекта. Эта копия будет находиться в объекте boundaries, но не связана с фактическим родительским объектом phase. Чтобы иметь возможность передавать родительский объект по ссылке, вам нужно handle к этому родительскому объекту, и для этого вам нужно определить родительский класс как handle.

...