Cell Array of Player Objects Not Printing All Fields - matlab

I've written a basic class definition as follows:
classdef player
properties
team
name
rating
ranking
end
methods
end
end
I get a cell array of player objects, called allPlayers, with every field but ranking already set. I then call the below function on it:
function setRankings(players)
for i = 1 : length(players)
players{i}.ranking = i;
end
end
At this point, all the fields of each player object should be set. I call the below function to display each field:
function displayPlayers(players)
for i = 1 : length(players)
current = players{i};
disp(['Name: ', current.name]);
disp(['Team: ', current.team]);
disp(['Rating: ', current.rating]);
disp(['Ranking: ', current.ranking]);
end
end
Unfortunately, each player prints out as follows (just an example):
'Name: ' 'Shleifer,Sam'
Team: Yale
'Rating: ' '5.050000'
Ranking:
So it looks like the ranking field doesn't actually get set by setRankings.
Why is this?

To get the behavior you desire you must make your class a 'handle' class - as opposed to a 'value' class. See this link for more information.
This is how to do it:
classdef player < handle
properties
team
name
rating
ranking
end
methods
end
end
Note that you can use value class too, but in that case you'd have to return the new list of players in setRanking.

Related

How to find objects with specific properties(another objects with specific properties) in Matlab?

For example, an object 'student' with a property 'test' , and 'test' is also an object with a property 'score'.
classdef student < handle
properties
name
test
end
methods
function obj = student(name)
obj.name = name;
obj.test = test();
end
end
end
classdef test < handle
properties
content
score
end
end
student_arr=[student('A') student('B')]
student_arr(1).test.score=100
student_arr(2).test.score=80
I want to find students whose score of test is 100. I use function findobj
findobj([student_arr.test],'score',100)
ans =
test with properties:
content: []
score: 100
It return a test array, not a student array.
But if I try to find it in the student_arr
findobj(student_arr,'score',100)
ans =
0×0 student array with properties:
name
test
It return a 0*0 student array, because 'score' is not a property of student.
The question is, if an object's property is another object, how to find the former based on properties of latter?
It is a bit undocumented, but you can use findobj with an additionnal function to specify the search:
H = findobj (student_arr, '-function', #(x) x.test.score == 100 );

How to store order of user input and update string

I am trying to make the field 'all names' display all of the selected 'names' (letters in this case) in the order they have been selected (assumed left-to-right). What I have written seems to only be functional if only the first transformation is applied and for the case A + E/F/G. All the rest do not work and I do not understand why.
The code for the first dropdown is this:
% Value changed function: DropDown
function DropDownValueChanged(app, event)
app.FirstName = app.DropDown.Value;
switch app.FirstName
case 'A'
app.FinalNameDrop.Value='A';
case 'B'
app.FinalNameDrop.Value='B';
case 'C'
app.FinalNameDrop.Value='C';
end
end
I was advised by an internet stranger that I can "define a property on the class itself!" and so I tried
properties (Access = private)
Property % Description
FirstName
SecondName
end
However, I am unsure how this can help me. How would I go about making this functional?
just put this in all callback methods:
app.dropDownFinal.Value = sprintf('%s + %s + %s',app.dropDown.Value app.dropDown2.Value app.dropDown3.Value);

How to find an object created by own class?

I created an object in MATLAB by using my own class my_class like this
car = my_class();
with
classdef my_class < handle
properties
color = 'red';
end
methods
function obj = my_class()
% ...
end
end
end
Now I am trying to find my object by its class (my_class) or by properties (color). But findall or findobj always return an empty matrix, whatever I am doing. Do you have any clue? Thanks.
EDIT I need something like this:
car1 = my_classA();
car2 = my_classA();
house1 = my_classB(); ... house25 = my_classB();
tree1 = my_classC(); ... tree250 = my_classC();
In my code, I can not refer to the names of the handles (like car2.color), because I have many different objects and I want to search for them by a function, that looks like the following one:
loop over all objects (maybe with findobj/findall without knowing object name/handle)
if object is of class `my_classA`
get handle of `my_classA`
change `color`
else if object is of class `my_classB`
get handle of `my_classB`
do something ...
end
end
I think you just want this:
% Create example array of objects
A(20) = object;
[A([3 14 17]).color] = deal('blue');
% Get those objects which are red, and change to orange
[A(strcmp({A.color}, 'red')).color] = deal('orange');
I have to admit, findobj would have been much better to read. But that only works on graphics handles as far as I'm aware, so you'd have to overload it for your class.
And that overloaded function, would contain something similar to this.
EDIT as noted by Navan, this works:
B = findobj(A, 'color', 'red');
[B.color] = deal('orange');
seems to be faster than the strcmp method, too.

How do I correctly implement the Factory Pattern in MATLAB?

I am writing a program in which I can select from a list of available Sensor objects; upon selection and user validation, the program should instantiate that Sensor.
The following code snippet is what I might naively do:
switch userInput
case 'Sensor A'
s = SensorA; % subclass of Sensor
case 'Sensor B'
s = SensorB; % subclass of Sensor
%...
end
There are some obvious problems here, but the biggest problem I have is making this extensible. I want to be able to create lots of various Sensor subclasses (or have other developers generate Sensor subclasses) without having to continuously add to this switch statement. More generally, I want to adhere to the open/closed principle. I ought to be able to have lots of different Sensor subclasses. (I also want to populate a popupmenu uicontrol with the available Sensors, but that probably gets solved if this problem gets solved generally.) Other naive solutions such as peeking into a folder full of Sensor subclasses doesn't work very well either, since object construction may be different for each subclass.
I believe I'm looking to use the factory method pattern, but I'm not entirely sure how to implement it. I could put the above code snippet into a separate SensorFactory, but this just moves the switch statement around, meaning extending it requires modifying it.
How do I implement the factory method pattern correctly such that the factory object doesn't require modification every time I add a new Sensor subclass?
Regarding extensibility you can use a containers.Map object as a hash table in your factory. Here is some simple example:
classdef SensorFactory < handle
% Lifetime
methods
function [factory] = SensorFactory()
% Creates the factory
% Call super class
factory = factory#handle();
% Pre-register some well-known sensors if you want
factory.RegisterSensor('Sensor A', #() error('TODO: Here of course use appropriate method to create sensor A'));
factory.RegisterSensor('Sensor B', #() error('TODO: Here of course use appropriate method to create sensor B'));
factory.RegisterSensor('Sensor C', #() error('TODO: Here of course use appropriate method to create sensor C'));
end
end
methods
function [] = RegisterSensor(factory, sensorName, createSensorCallback)
% Adds new sensor to the factory
factory.dictionnary(sensorName) = createSensorCallback;
end
function [sensorList] = GetListOfSensors(factory)
% Obtains the list of available sensors
sensorList = factory.dictionnary.keys;
end
function [sensor] = CreateSensor(factory, sensorName)
% Creates sensor instance
createCallback = factory.dictionnary(sensorName);
sensor = createCallback();
end
end
properties(GetAccess = private)
dictionnary = containers.Map(); % Hash table
end
end
This class can be used like this:
At the beginning of the code create the factory:
factory = SensorFactory();
In some initialization part add new sensors on the fly:
factory.RegisterSensor('Custom Sensor', #() createCustomSensor());
factory.RegisterSensor('Specific Sensor aperture=42', #() createSpeficSensor(42));
factory.RegisterSensor('Specific Sensor aperture=666', #() createSpecificSensor(666));
NB: For automation purpose, this may be done also parsing class files in some folder. Each class having a static method to get the user name of the sensor. Just some thoughts and pseudo code here:
classdef MySuperSensor
methods(Static)
funcion [name] = GetUserName()
name = 'My super sensor';
end
end
end
---
l = dir('.\sensors');
foreach file in l
try
meta = eval(sprintf('?%s', l.name));
factory.Register(...GetUserName()..., ...CreateCallback...)
catch
end
end
Then, in some GUI part, add a combo listing all available sensors to date:
set(myCombo, 'String', factory.GetListOfSensors());
Finally, in the run part, instantiate appropriate sensor:
index = get(myCombo, 'Value');
name = factory.GetListOfSensors();
name = name{index};
sensor = factory.CreateSensor(name);
I don't really see a reason to use the factory pattern here. A typical piece of code for matlab is:
if ischar(fun)
if exist(fun,'function')
fun=str2func(fun)
else
error('invalid input')
end
end
if ~isa(fun, 'function_handle')
error('invalid input')
end
sensor=fun()
Using this, fun can be name or function handle to a function or constructor which returns your sensor object.

Self reference within an object method

Just started crash coursing in Matlab OO programing and I would like to write a set method for a object that will set the value then reciprocate by setting itself in the relevant field on the other object.
classdef Person
properties
age;
sex;
priority; % net priority based on all adjustment values
adjustment; % personal adjustment value for each interest
family;
end
methods
function obj = set.sex(obj, value)
if value == 'm' || value == 'f'
obj.sex = value;
else
error('Sex must be m or f')
end
end
function obj = set.family(obj,value)
if class(value) == 'Family'
obj.family = value;
else
error('Family must be of type Family')
end
end
end
end
classdef Family
properties
husband;
wife;
children;
elders;
adjustment; % interest adjustment values
end
methods
function this = set.husband(this,person)
if class(person) == 'Person'
this.husband = person;
person.family = this;
else
error('Husband must be of type Person')
end
end
function this = set.wife(this,person)
if class(person) == 'Person'
this.wife = person;
person.family = this;
else
error('Wife must be of type Person')
end
end
end
end
So what I have to do now is:
p = Person
f = Family
f.husband = p
p.family = f
What I would like is for family and person to auto set themselves in each other:
p = Person
f = Family
f.husband = p
And Family set.husband function will set p's family value to f. Why is my code not working? As far as I can tell I'm doing what is suggested in the comments.
Edit:
After some messing around I've confirmed that "this" and "person" are objects of the correct type. Ultimately the issue is that Matlab passes by value rather then by reference. Unless anyone knows a way around that I'll answer myself when I can.
Normal objects are usually considered value objects. When they are passed to a function or a method, only the value is passed not a reference to the original object. Matlab may use a read-only referencing mechanism to speed things up, but the function or method cannot change the properties of the original object.
To be able to pass an input parameter by reference, your custom object needs to be a handle object. Simply when defining your class, inherit from handle and that should do the trick:
classdef Person < handle
and
classdef Family < handle