What is best way to define 2 way dependence between class properties

17 views (last 30 days)
Say I am defining a class called Point which describes a point in 3D space. The class has a coordinate property which is a 3 entry vector ([x, y, z]) and also a separate property for each component of the coordinate (Point.X, Point.Y, and Point.Z).
A point object is always instantiated using a coordinate vector but, once instantiated, I would like the user to be able to update the value of either the coordinate vector OR the individual component values and have the two stay consistent with each other, in other words:
If the user changes the coordinate vector:
Point.coord = [newX, newY, newZ]
The X, Y and Z properties should be updated to newX, newY and newZ respectively
OR, if the user updates one of the X, Y or Z properties:
Point.X = newerX;
Point.Y = newerY;
Point.Z = newerZ;
The coord property should be updated to [newerX, newerY, newerZ]
What is the preffered way to implement this? Is it even possible at all?
My first thought was to just update the coordinate vector in the set.X, set.Y and set.Z methods and vice versa but I'm guessing this will cause some sort of infinite loop and Matlab complains saying you shouldn't set the values of properties inside the set method of another property. I know that one way dependence is easy to define using dependent properties but for this 2 way dependence I am stumped.

Accepted Answer

Steven Lord
Steven Lord on 4 Oct 2019
You have essentially two "views" into one underlying "truth". While you can ignore the warning, I would make both the "view" properties Dependent upon one private "truth" property.
classdef Temperature
properties(Access=private)
Kelvin
offsetC = -273.5;
end
properties(Dependent)
Celcius
Fahrenheit
end
methods
function obj = Temperature(temp, unit)
switch lower(unit(1))
case 'c'
obj.Celcius = temp;
case 'f'
obj.Fahrenheit = temp;
otherwise
error('Expected a temperature in C or F')
end
end
function y = get.Celcius(obj)
y = obj.Kelvin + obj.offsetC;
end
function obj = set.Celcius(obj, newvalue)
obj.Kelvin = newvalue - obj.offsetC;
end
function y = get.Fahrenheit(obj)
y = c2f(obj.Celcius);
end
function obj = set.Fahrenheit(obj, newvalue)
obj.Celcius = f2c(newvalue);
end
function seeValueOfKelvin(obj)
fprintf('The temperature in Kelvin is %f.\n', obj.Kelvin);
end
end
end
function c = f2c(f)
c = (f-32)*(5/9);
end
function f = c2f(c)
f = (9/5)*c+32;
end
Here's how you can use this:
>> obj = Temperature(0, 'C')
obj =
Temperature with properties:
Celcius: 0
Fahrenheit: 32
>> obj.Fahrenheit = 212
obj =
Temperature with properties:
Celcius: 100
Fahrenheit: 212
>> seeValueOfKelvin(obj)
The temperature in Kelvin is 373.500000.
The "truth" is the temperature in Kelvin. Both the temperature in Celcius and in Fahrenheit are derived from Kelvin.

More Answers (1)

Gaurav Garg
Gaurav Garg on 4 Oct 2019
Hi,
Assuming you are using MATLAB R2019a, you can set a property in other property’s set method, though it shows a warning. So, you can set the properties of Point X, Y and Z in the set method of coord.
Also, if you go through the documentation of the Set methods, it mentions that MATLAB does not call a property set method if value is assigned to a property from within its own property set method, to prevent recursive calling of the set method.
For better understanding, we look on the code below. Run the code as a script and type o=PropertySetMethod("method") in the command window.
In line 11, we display str, and the output for str is method” (the string which was passed in while creating object for the class).
In line 12, we set Prop1 property of obj. The point to be noted here is that set method gets called here (defined in line 18) and the string “Inside constructor” is passed as argument str. In line 20, Prop2 property of PropertySetMethod is set as str. This returns just a warning and not an error.
classdef PropertySetMethod
properties
Prop1 = "Default String"
Prop2 = "My string"
end
methods
function obj = PropertySetMethod(str)
if nargin > 0
fprintf("Before setting prop1, str = %s\n",str);
obj.Prop1 = "Inside constructor";
fprintf("After setting prop1, str = %s\n",str);
end
end
function obj = set.Prop1(obj,str)
obj.Prop1 = str;
obj.Prop2 =str;
fprintf('set.Prop1 method called. Prop1 = %s and this is str = %s\n', obj.Prop1,str);
end
end
end

Categories

Find more on Construct and Work with Object Arrays in Help Center and File Exchange

Community Treasure Hunt

Find the treasures in MATLAB Central and discover how the community can help you!

Start Hunting!