- When are pressure vessels allowed to change pipes? Are they fixed when the pressure vessels are created or can they be changed at all?
- Can you have a pipe without a pressure vessel?
- Can you have a pressure vessel without a pipe?
- Who is allowed to query and/or change a pressure vessel's mass flow rate? Can the pressure vessel? Can either of its associated pipes?
- Who is allowed to query and/or change a pipe's mass flow rate? Can the pipe itself? Can the pressure vessel with which it's associated?
- What is the interaction between a pressure vessel's mass flow rate and its inlet and outlet pipe's mass flow rate?
- If a pipe must be associated with a pressure vessel, and if its mass flow rate can change to a value that's incompatible with the pressure vessel's, whose responsibility is it to detect that incompatibility?
- What actions should you be able to take on a pressure vessel?
- What actions should you be able to take on a pipe?
Set properties of child objects without synchronisation errors
3 visualizaciones (últimos 30 días)
Mostrar comentarios más antiguos
I have a parent object with properties which hold some child objects. The child objects are all of the same class. When I change certain properties of the parent object I would like the equivalent child object properties to change too. For example
classdef PressureVessel
properties
massFlowRate % mass flow rate through the pressure vessel
inletConnection ConnectingPipe % pipe which is the inlet to the pressure vessel
outletConnection ConnectingPipe % pipe which is the outlet to the pressure vessel
end
methods
function vesselObj = set.massFlowRate(vesselObj,flowRate)
% Set the mass flow rate through the vessel, and through each of the nozzles, to be equal
% Causes warning about "The set method should not access another property"
vesselObj.massFlowRate = flowRate;
vesselObj.inletConnection.massFlowRate = flowRate;
vesselObj.outletConnection.massFlowRate = flowRate;
end
end
end
The connecting pipe class is as follows
classdef ConnectingPipe
properties
massFlowRate % mass flow rate through the connecting pipe
velocity % velocity of fluid, calculated from the mass flow rate
end
end
I can see from the warning and reading the documentation that this is not good practice and can cause property initialisation order dependency problems. Is there a better way of achieving the desired behaviour? Should the ConnectingPipe objects be told what their parent object is when they are created, and then pull the mass flow rate from the parent? Ideally I'd like to be able to use the ConnectingPipe object without a parent so that would be non-preferred. I'm not clear how the use of a private property (see example here: https://uk.mathworks.com/help/matlab/matlab_oop/avoiding-property-initialization-order-dependency.html) can help in this situation, and I'd rather avoid it if possible because there are loads of properties which this applies to, and I don't think it will be obvious to the next user of the code what is going on.
Any suggestions gratefully received.
0 comentarios
Respuestas (4)
Steven Lord
el 5 de Dic. de 2019
Let's take a step back from the code for a second. Can you describe the design of your system for which this set of classes will be the implementation?
You have a pressure vessel. That pressure vessel has two pipes, named inlet and outlet, and a mass flow rate.
Each pipe has its own mass flow rate.
Knowing the answers to some of these questions will help determine how tightly coupled the software modeling those objects should be. [I hope that the physical pressure vessel and its pipes are tighly coupled, say with strong welds, especially if high pressures are involved!]
1 comentario
Guillaume
el 5 de Dic. de 2019
This is a very good point by Steven and my answer and comments are only valid if you're trying to simulate some air flow through a system of pipes/components with no loss of mass (so mass flow is constant throughout) as you would with GT-power or similar software. That's what my students are doing now, so I didn't think of anything else. But indeed, depending on the answers to the above questions a completely different design would be much better.
J. Alex Lee
el 5 de Dic. de 2019
Is your "ConnectingPipe" class really just the 2 properties, or is that just part of the class? If it's only 2 properties, would you consider not having them be their own classes? I suppose on name/context you'd want the "ConnectingPipe" to be endowed with other things like diameter, and perhaps a method to compute velocity from the diameter and massflowrate...
Can you just give your ConnectingPipe class a property that refers to its parent vessel object, and then make its massFlowRate a dependent property, which will read its parent vessel's massFlowRate on-demand? Is this also bad practice?
classdef ConnectingPipe
properties
ParentVessel PressureVessel
Diameter double
end
properties (Dependent)
massFlowRate
velocity
end
methods
function this = ConnectingPipe(ParentVessel,Diameter)
this.ParentVessel = ParentVessel;
this.Diameter = Diameter;
end
function out = get.massFlowRate(this)
out = this.ParentVessel.massFlowRate;
end
function out = get.velocity(this)
out = this.massFlowRate / (pi*D^2/4);
end
end
end
and
classdef PressureVessel
properties
massFlowRate
inletPipe ConnectingPipe
outletPipe ConnectingPipe
end
methods
function this = PressureVessel(massFlowRate)
this.massFlowRate = massFlowRate;
this.inletPipe.ParentVessel = this;
this.outletPipe.ParentVessel = this;
end
% no more need for set function for massFlowRate
end
end
Also just found this, which makes it seem the above strategy is not so bad, https://www.mathworks.com/matlabcentral/answers/158010-get-property-of-the-parent-object
3 comentarios
J. Alex Lee
el 5 de Dic. de 2019
Oops, sorry I didn't see the stipulation.
However, my understanding about the warning is about the unpredictable order of property-setting, not about inadvertent access to properties that are "downstream" of some chain of operations...so while in this simple example the privatizing will practically solve the danger, it wouldn't necessarily eliminate the warning, right?
Also, would it not be harder to maintain this strategy as you kept adding shared properties among these 2 classes, so that you would need to keep worry about adding/updating the set methods for "shared" properties?
I think Guillaume's answer with the handle class for massflow makes more sense!
Guillaume
el 5 de Dic. de 2019
The reason for the warning is that if you're not careful it's easy to have the three mass flows disconnected from each other. For example, with the initial design, you can set the mass flow in the pressure vessel which sets the mass flow in the pipes and then inadvertently override that by accessing the property of the pipe. Thus, forcing the pipe property to be handled by the pressure vessel avoids that issue.
You also have to consider reloading the classes from a mat file which again could result in different values in properties that are essentially the same. This shouldn't be an issue with the original design.
The warning is a warning and not an error because you can use this design if you're careful.
If there are more shared properties between the classes, then my handle class solution is even more worhwile since all the shared properties can be stored in that single handle class and you're guaranteed that all the classes are always using the same properties.
Guillaume
el 5 de Dic. de 2019
As I wrote in my comment to J. Alex, I don't see a problem with your initial design if the pipes can't be modified outside of the PressureVessel class (i.e. the pipes are private properties of the vessel).
Otherwise, I'd use a handle class to store the mass flow and share an instance between all three class:
classdef MassFlow < handle
properties
value;
end
end
classdef PressureVessel
properties
inletConnection ConnectingPipe % pipe which is the inlet to the pressure vessel
outletConnection ConnectingPipe % pipe which is the outlet to the pressure vessel
end
properties (SetAccess = private)
massFlowRate MassFlow = MassFlow();
end
methods
function this = PressureVessel
this.inletConnection.massFlowRate = this.massFlowRate; %share the same MassFlow variable between all three
this.outletCOnnection.massFlowRate = this.massFlowRate;
end
end
%...
end
classdef ConnectingPipe
properties
velocity % velocity of fluid, calculated from the mass flow rate
end
properties (SetAccess = ?PressureVessel) %can be set by PressureVessel (when it's constructed
massFlowRate MassFLow = MassFlow();
end
end
PV = PressureVessel;
PV.massFlowRate.value = 4; %automatically set the connecting pipes mass flow rate
PV.inletConnection.massflowRate %displays 4
PV.inletConnection.massFlowRate = 6;
PV.massFlowRate.value %displays 6
pipe = ConnectingPipe; %connecting pipes without a parent
pipe.massFlowRate.value = 8;
4 comentarios
Guillaume
el 5 de Dic. de 2019
Editada: Guillaume
el 5 de Dic. de 2019
Your new design is not a good idea. It mixes dependent property pattern with a non-dependent property and there would be a real risk that one of the mass flow is not in sync with the other. I particularly dislike the design of your set.massFlowRate function which may result in unexpected behaviour.
As I said to J. Alex, the handle class becomes extremely useful if you have other properties shared between the components. But I can't really think of any other property of the pipework that wouldn't be local.
In my opinion, your initial design is indeed fine. However, pay heeds to my comment on access properties. If the mass flow is controlled by the plenum, you cannot allow it to be set directly by the pipe. Otherwise, you allow one to be disconnected from the other.
Ver también
Categorías
Más información sobre Beamforming en Help Center y File Exchange.
Productos
Community Treasure Hunt
Find the treasures in MATLAB Central and discover how the community can help you!
Start Hunting!