[Warning] Why is it bad practice to set additional class properties when using a set method (prompting a warning)?

15 ビュー (過去 30 日間)
I have a class with several properties, and I want it so that if I set one of those properties, it effectively resets additional properties. Now, these are not fully dependent properties, since I want to be able to manipulate them as well. Here is a MWE
classdef testClass
properties
A(2,1) double = [5;1];
B(1,1) double
end
methods
function obj = set.A(obj,val)
obj.A = val;
obj.B = sum(obj.A); % This is where the warning pops in
end
function obj = doThing(obj)
obj.B = 2*obj.B;
end
end
end
The warning reads "The set method for propery 'A' should not access another property ('B')". The more detailed warning talks about dependency issues and ordering. Now, again, B is not a dependent or transient property.
I know I can do various things to make sure that there are no errors because of this: 'B' initializes as 0 because I have defined it in the properties block, and I can get the "proper" starting value by including something like this in the constructor:
function obj = testClass
obj.B = sum(obj.A);
end
So, my question is whether this is still bad coding practice despite taking care that properties are appropriately set? Is there another, better way of resetting certain semi-dependent properties when another property is modified.
Cheers,
-DP

採用された回答

Steven Lord
Steven Lord 2019 年 3 月 28 日
Be very careful not to get yourself into a recursive situation like the class I posted earlier this month for this Answer does.
I would probably make B a Dependent property with a get.B method that accesses the A property. See this documentation page for some information about dependent properties.
A couple observations about your class:
  1. Your default value for the A property does not satisfy the size validation you've listed in your file. Either the default value should be [5; 1] or you should require A to be of size [1 2].
  2. Your doThing method doesn't make sense to me. As written it would make B out of sync with A. You could have doThing update A then the value of the Dependent property B would also be doubled. [I would not define a set.B method, or if I did I would implement it so it throws a user-friendly error message.]
function obj = doThing(obj)
obj.A = 2*obj.A;
end
  2 件のコメント
D. Plotnick
D. Plotnick 2019 年 3 月 28 日
Fixed (1).
(2) Part of the point is to let B get out of sync with A, but that A always determines a starting point.
An analogy: B as a sandbox that I can play in, while A is the playground where the sandbox is installed. Each time I directly change A (swap playgrounds), I have to start with a fresh sandbox, whose starting properties are determined by the the property values of A. Once it is re-initialized, I can start mucking about with B again.
Thanks for the recursion example, I have been pretty concerned about that exact issue of cross-linking multiple properties.
Guillaume
Guillaume 2019 年 3 月 29 日
In that case, you can just silence the mlint warning.
However, personally, I'd make A a private property and provide an explicit changePlayground method instead. It makes the intent clearer to the user.
classdef testClass
properties (Access = private)
A(2,1) double = [5;1];
end
properties
B(1,1) double
end
methods
function obj = changePlayground(obj, val)
obj.A = val;
obj.B = sum(obj.A);
end
function obj = doThing(obj)
obj.B = 2*obj.B;
end
end
end

サインインしてコメントする。

その他の回答 (1 件)

TADA
TADA 2019 年 3 月 28 日
編集済み: TADA 2019 年 3 月 28 日
The thing is that dependent properties always invoked their get/set methods every time you access them. what you did doesn't necessarily create bugs. But to be on the safe side and get rid of the warning you can make A a dependent property and have it save its value in a private property, let's call it A_:
classdef testClass
properties (GetAccess=private,SetAccess=private)
A_(2,1) double = [5,1];
end
properties
B(1,1) double;
end
properties (Dependent)
A;
end
methods
function obj = set.A(obj,val)
obj.A_ = val;
obj.B = sum(obj.A);
end
function a = get.A(object)
a = object.A_;
end
function obj = doThing(obj)
obj.B = 2*obj.B;
end
end
end

カテゴリ

Help Center および File ExchangeNumerical Integration and Differential Equations についてさらに検索

Community Treasure Hunt

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

Start Hunting!

Translated by