Filter löschen
Filter löschen

Property Type in constructor vs dependent

1 Ansicht (letzte 30 Tage)
Timo Kuchheuser
Timo Kuchheuser am 22 Mai 2024
Kommentiert: Timo Kuchheuser am 23 Mai 2024
I am using a function handle in a class and there seems to be a difference whether I set it in properties or in dependent properties. In the second case I need to add a cast to my property or else it doesn't work.
There seems to be some type related thing I do not understand.
Thank you for your help!
Function
This is the function and it's execution (in the class D_b is defined as a double):
D_b = 19;
f = @(t)(D_b/2)*(cos(t)+t.*sin(t));
x = f(linspace(0,pi/4,50)');
Works without cast
When I define it in properties and initialize it via the constructor like below, it works:
properties(SetAccess=immutable, GetAccess=public)
% Base circle diameter
D_b double
% Involute function x axis
i_x function_handle
end
function obj = Spur()
%....
obj.D_b = 38; %Example
obj.i_x = @(t)(D_b/2)*(cos(t)+t.*sin(t));
%....
end
Fails without cast
When I try to use dependents it fails unless I cast D_b/2 to a double:
properties (Dependent)
D_b double
i_x function_handle
end
methods
function db = get.D_b(obj)
db = double(obj.D*cosd(obj.phiDegrees)); %CASTING
end
function ix = get.i_x(obj)
ix = @(t)(obj.D_b/2)*(cos(t)+t.*sin(t));
end
end
If I don't cast the following error occures (which is not the case with my first approach):
Error using *
Integers can only be combined with integers of the same class, or scalar doubles.
Error in Spur>@(t)(obj.D_b/2)*(cos(t)+t.*sin(t)) (line 97)
ix = @(t)(obj.D_b/2)*(cos(t)+t.*sin(t));
  3 Kommentare
Adam
Adam am 22 Mai 2024
Spur() is the constructor so this kind of property initialisation works fine. If obj hasn't yet been referenced when you assign to a property in the constructor it will create it at that moment.
For the rest, I'm a little confused what the actual problem is, what is working and what isn't, from the example given.
Timo Kuchheuser
Timo Kuchheuser am 22 Mai 2024
Sorry for being confusing. I will provide both classes below. I wanted to know why in one case my function (i_x) works without casting and in the other case gives me an error when not casting. Where in my code am I loosing the type class information?
Thank you!!!
Works
classdef SpurWorkingWithoutCast
properties(SetAccess=immutable, GetAccess=public)
m double
N uint8 {mustBeInteger, mustBeNonnegative, mustBeGreaterThan(N,1)}
phiDegrees double {mustBeNonnegative}
D double
D_b double
i_x function_handle
end
methods
function obj = SpurWorkingWithoutCast(m,N,phiDegrees)
obj.m = m;
obj.N = N;
obj.phiDegrees = phiDegrees;
obj.D = obj.m*obj.N;
obj.D_b = obj.D*cosd(obj.phiDegrees);
obj.i_x = @(t)(obj.D_b/2)*(cos(t)+t.*sin(t));
end
end
end
Execute
l = linspace(0,pi/4,50)';
sw = SpurWorkingWithoutCast(2,20,20);
x = sw.i_x(l)
Does not work
classdef SpurWorkingOnlyWithCast
properties(SetAccess=immutable, GetAccess=public)
m double
N uint8 {mustBeInteger, mustBeNonnegative, mustBeGreaterThan(N,1)}
phiDegrees double {mustBeNonnegative}
end
properties (Dependent)
D double
D_b double
i_x function_handle
end
methods
function d = get.D(obj)
d = obj.m*obj.N;
end
function db = get.D_b(obj)
%db = double(obj.D*cosd(obj.phiDegrees));
db = obj.D*cosd(obj.phiDegrees);
end
function ix = get.i_x(obj)
ix = @(t)(obj.D_b/2)*(cos(t)+t.*sin(t));
end
end
methods
function obj = SpurWorkingOnlyWithCast(m,N,phiDegrees)
obj.m = m;
obj.N = N;
obj.phiDegrees = phiDegrees;
end
end
end
Execute
l = linspace(0,pi/4,50)';
sf = SpurWorkingOnlyWithCast(2,20,20);
x = sf.i_x(l)
Error using *
Integers can only be combined with integers of the same class, or scalar doubles.
Error in SpurWorkingOnlyWithCast>@(t)(obj.D_b/2)*(cos(t)+t.*sin(t)) (line 26)
ix = @(t)(obj.D_b/2)*(cos(t)+t.*sin(t));

Melden Sie sich an, um zu kommentieren.

Akzeptierte Antwort

Matt J
Matt J am 22 Mai 2024
Bearbeitet: Matt J am 22 Mai 2024
Property type specifiers, such as the double specifier in,
properties (Dependent)
D_b double
end
only perform conversions when a value is assigned to the property, not when values are extracted from it. That is true regardless of whether the property is Dependent or not. However, a consequence of D_b being Dependent in your particular design of SpurWorkingOnlyWithCast is that you never assign and store a value to the D_b property, so the double specifier above isn't really doing anything. Only the get.D_b() method is determining the type of the returned value db.
Note that the property type specifier isn't always irrelevant when dealing with Dependent properties. If you had defined a set.D_b() method in SpurWorkingOnlyWithCast, then the double specifier would cause any assignment of the form obj.D_b=val to pre-convert val to double before passing it to set.D_b().
Ultimately, I think the best solution is to get rid of the casting of N to uint8. There is no reason to have that if you are going to be deriving non-integer quantities from N:
properties(SetAccess=immutable, GetAccess=public)
N {mustBeInteger, mustBeNonnegative, mustBeGreaterThan(N,1)}
...
end
  1 Kommentar
Timo Kuchheuser
Timo Kuchheuser am 23 Mai 2024
Thank you very much for your explanation! Removing the uint8 worked.

Melden Sie sich an, um zu kommentieren.

Weitere Antworten (0)

Produkte


Version

R2024a

Community Treasure Hunt

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

Start Hunting!

Translated by