Matlab инициализирует массив объектов - PullRequest
6 голосов
/ 25 мая 2011

Я играю с ООП в MATLAB, и у меня есть следующий конструктор:

function obj = Squadron(num_fighters, num_targets, time_steps)            
    if nargin == 0
        num_targets = 100;
        time_steps = 100;
        num_fighters = 10;
    end
    obj.num_shooters = num_fighters;
    for iShooter = 1:obj.num_shooters
       a(iShooter) = Shooter(num_targets, time_steps);
    end
    obj.ShooterArray = a;
    obj.current_detections = zeros(num_fighters, num_targets);
end

Эта временная переменная 'a' пахнет ужасно.Есть ли лучший способ инициализировать массив объектов, я хотел бы, чтобы был метод push / pop.Я уверен, что есть лучший способ сделать это.

Ответы [ 2 ]

10 голосов
/ 20 октября 2011

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

Короче: то, что вы делаете, может быть не очень красиво, но уже может быть довольно хорошо.

При создании массива в Matlab обычно хорошей идеей является предварительное выделение резервной памяти, что значительно повышает производительность.

В обычном случае что-то вроде этого:

a=zeros(1,1000);
for n=1:1000
    a(n)=n;
end

(здесь a = 1: 1000; было бы еще лучше)

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

a(1,1000)=ObjectConstructor();
for n=1:1000
    a(n)=ObjectConstructor();
end

или просто

for n=1000:-1:1
    a(n)=ObjectConstructor();
end

Убедившись, что Shooter можно вызывать без аргументов, вы должны иметь возможность сделать что-то вроде:

for iShooter = obj.num_shooters:-1:1
   obj.ShooterArray(iShooter) = Shooter(num_targets, time_steps);
end

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

Я бы попробовал:

for iShooter = obj.num_shooters:-1:1
   a(iShooter) = Shooter(num_targets, time_steps);
end
obj.ShooterArray = a;

Еще раз - для получения дополнительной информации.подробнее см. это обсуждение

4 голосов
/ 25 мая 2011

Есть несколько способов справиться с этой ситуацией ...

  • Создание массивов объектов в конструкторе:

    Вы можете изменить класс Shooter так, чтобы при передаче массивов значений он создавал массив объектов.Затем вы можете инициализировать ShooterArray следующим образом:

    obj.ShooterArray = Shooter(repmat(num_targets,1,num_fighters),...
                               repmat(time_steps,1,num_fighters));
    
  • Репликация экземпляров класса значений:

    Если Shooter является значение класса , и каждый объект будет точно одинаковым (т.е. вы не инициализируете ни одно из его свойств по умолчанию случайными значениями), тогда вы можете создать только один объект ископируйте его, используя REPMAT :

    obj.ShooterArray = repmat(Shooter(num_targets,time_steps),1,num_fighters);
    

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

Добро пожаловать на сайт PullRequest, где вы можете задавать вопросы и получать ответы от других членов сообщества.
...