1

I am new to object-oriented programming. Let's say I have several objects of different classes:

Ford (class: car)

VW (class: car)

cat (class: animal)

Boeing (class: plane)

Now I want to run a function calculateSpeed on every object of class car and plane. I understand that I have to go through all workspace variables, identify the sought objects and pass them to my function:

myvars = whos;
for i = 1:numel(myvars)
    if isa(myvars(i),'car') | isa(myvars(i),'plane')
       calculateSpeed(myvars(i));
    end
end

Obviously it's not working, because I do not pass the actual object but just the reference of the object within myvars to the function. How can I neatly run a function on specific objects?

Update (see comments):

My classdef file car.m looks like the following:

classdef car  
    properties
        a;
        e;
        i;
    end    
    methods      
    end
end

My function calculateSpeed looks like this:

function [ speedArray ] = calculateSpeed(object)
T = 2 * pi() * sqrt(object.a^3);
[...]
end

Matlab gives me the error Reference to non-existent field 'a'. I assume, because the function is not operating with the actual object, but with the struct created by whos.

1 Answer 1

1

Ok actually, cycling through all workspace variables is not considered a best practice. If your workspace contains a lot of variables, and a majority of them are not necessary for your calculations, you are just gonna spend a lot of time to accomplish this task with no reason.

There must be a moment in which you allocate / instantiate those classes in your code, and that would be a great moment to insert them into different cell arrays that hold the different exiting categories of objects. That way, you will just have to apply your code to all the instances inside the target cell arrays to obtain the desired result.

Another good idea is to create a superclass called, for example, Vehicle, that both Car and 'Plane' classes will inherit. Then, you can define your function calculateSpeed into the superclass, so you can keep on working on generic class profiles and avoid checking many different type of classes. But this would be tricky if you insist on sticking with cycling workspace variables.

Option 1 with workspace variables:

% Animal Categories

classdef Animal < handle 
    % ...
end

% Vehicle Categories

classdef (Abstract) Vehicle < handle
    properties
        Speed
    end

    methods
       function CalculateSpeed(this)
           this.Speed = 100; % your calculations here
       end
    end
end

classdef Car < Vehicle
    % ...
end

classdef Plane < Vehicle
    % ...
end

% Script Code

Ford = Car();
VW = Car();
Boeing = Plane();
car = Animal();

vars = whos();

for i = 1:numel(vars)
    var_curr = vars(i);

    if (strcmp(var_curr.class,'Car') || strcmp(var_curr.class,'Plane'))
        eval([var_curr.name '.CalculateSpeed()']);
    end
end

Option 2 with full control over instances allocation:

% Animal

classdef (Abstract) Animal < handle
    % ...
end

% Vehicle

classdef Vehicle < handle
    properties
        Name
        Speed
        Type
    end

    methods
        function this = Vehicle(type,name)
            this.Type = type;
            this.Name = name;
            this.CalculateSpeed();
        end
    end

    methods
       function CalculateSpeed(this)
           switch (this.Type)
                case 'Car' 
                    this.Speed = 50;
                case 'Plane'
                    this.Speed = 150;
                otherwise
                   this.Speed = 0;
           end
       end
    end
end

% Script Code

insts = cell(10,1);

for i = 1:10
    insts{i} = Vehicle(type,name);
end

If you don't want to calculate the speeds directly when the object is instantiated, then just comment the call to the method in the constructor and run a loop to do it when necessary:

for i = 1:10
    insts{i}.CalculateSpeed();
end

Option 3, let's keep using your idea:

vars = whos();

for i = 1:numel(vars)
    var_curr = vars(i);

    if (strcmp(var_curr.class,'Car') || strcmp(var_curr.class,'Plane'))
        s = eval(['calculateSpeed(' var_curr.name ')']);
    end
end

On a side note, logical operators in if conditions must be double. Single logical operators can only be used between two logical operators in an indexing context. Also, always try to cache your indexing results because for loops in Matlab are expensive, and this can save up a lot of time in big cycles.

Sign up to request clarification or add additional context in comments.

1 Comment

Having a look at how you defined your classes could be helpful. Anyway I'll edit my answer trying to clarify your doubts

Your Answer

By clicking “Post Your Answer”, you agree to our terms of service and acknowledge you have read our privacy policy.

Start asking to get answers

Find the answer to your question by asking.

Ask question

Explore related questions

See similar questions with these tags.