MATLAB Answers

checking dataType instead typecast at property or argument validation

4 views (last 30 days)
Hello, I would like to use property/ argument validation in a different way. I would like to prevent the assignment of other types as the specified meta.Validation.Class.
As an example:
I've the following class
classdef TestPropertyValidation
properties
myProperty double {mustBeNumeric}
end
methods
function obj = TestPropertyValidation(stringVal)
obj.myProperty = stringVal;
end
end
end
If I pass now ...
>> TestPropertyValidation("Hello")
ans =
TestPropertyValidation with properties:
myProperty: NaN
I guess because of the conversion:
>> double("Hello")
ans =
NaN
>> isnumeric(NaN)
ans =
logical
1
But I like the way specifying conditions for properties. And I would like to use it in a bigger project. There we have to make sure no uncontrolled conversions happen between object constructor calls with lots of paramters passed to constructors and methods. I would like to prevent that for example 1+'1' := 50 operations can happen because of a misplaced method parameter for example.
I know I can use the ValidatorFunctions to prevent that for example a character is passed instead a double but only if I don't state the desired class, for example 'double' to don't have a conversion. It would be very nice having the type check and afterwards the validatorFunctions for further conditions to values. Is there a way to change the validation of properties and arguments to have a validation of the class instead of a conversion at validation order step 1.
Thank you.

  0 Comments

Sign in to comment.

Accepted Answer

Sean de Wolski
Sean de Wolski on 11 Feb 2020
There's no way to do this with validators in R2019b and the datatype coercion will always happen. You can use a set.property setter method to type check new values.

  0 Comments

Sign in to comment.

More Answers (3)

Henry Gotjen
Henry Gotjen on 11 Feb 2020
Hi Florian,
I recently learned this property validation as well, and its been working for me.
Your syntax is backwards, if you're using {mustBeNumberic} you don't have to specify double. In fact, the double delcaration seems to be overwriting the metaclass validator. I tried your code with:
classdef TestPropertyValidation
properties
myProperty {mustBeNumeric}
end
methods
function obj = TestPropertyValidation(stringVal)
obj.myProperty = stringVal;
end
end
end
and got
>> test = TestPropertyValidation("hello")
Error using TestPropertyValidation (line 7)
Error setting property 'myProperty' of class 'TestPropertyValidation':
Value must be numeric.
>> test = TestPropertyValidation('word')
Error using TestPropertyValidation (line 7)
Error setting property 'myProperty' of class 'TestPropertyValidation':
Value must be numeric.
>> test = TestPropertyValidation([1 2 3 4])
test =
TestPropertyValidation with properties:
myProperty: [1 2 3 4]

  0 Comments

Sign in to comment.


Steven Lord
Steven Lord on 11 Feb 2020
If you specify both a property validator function and a class name, I believe MATLAB will cast the property name you try to set to that class before calling the property validator functions. In the "Using Validation Functions" section on this documentation page it states "Because the Data property validation does not include a numeric class, there is no conversion of the char vector to a numeric value. If you change the validation of the Data property to specify the class as double, MATLAB converts the char vector to a double array." and then "The assignment to the char vector does not produce an error because MATLAB converts the char vector to class double."
As the example in that section shows, if you don't include a class name MATLAB won't have anything to cast the property value to before it calls the property validator function.
If you want to restrict the property values even further, not just requiring them to be numeric but requiring them to be double, you could write your own local validator function similar to mustBeNumeric. You could call it mustBeDouble. See the "Define Validation Functions" section on that documentation page for an example you could use as a model

  4 Comments

Show 1 older comment
Henry Gotjen
Henry Gotjen on 11 Feb 2020
By why of answering myself, no it doesn't work. I think best to
classdef TestPropertyValidation
properties
myProperty {mustBeNumeric}
end
methods
function obj = TestPropertyValidation(stringVal)
obj.myProperty = stringVal;
end
% include a setter, forcing things like uint16 to be double.
% validator will reject non-numeric inputs before setter runs.
function obj = set.myProperty(obj,newprop)
obj.myProperty = double(newprop);
end
end
end
Jan Tusch
Jan Tusch on 18 Feb 2020
IMHO, it isn't getting any better by documenting this counterinituitive behavior. When I first learned about this feature I was really happy to be able to express some type conventions to the user of my class. Thereby, making it really speaking code in the spirit of an interface definition. That said, I would expect the "validation" to do just what it is named after: validate the value beeing set to conform to my constraints.
However, all the magic under the hood performing conversion and scalar expansion renders this feature complete unsave (in the sense of an interface description), anyone can assign anything to my property als long as it is convertible. It makes sure the value conforms to my constraints by fiddling around to make it match.
Who in the world needs scalar expansion in an assignment? Use the colon. This is just a temptation to write sloppy code.
What is the benefit of this "validation" feaure in the first place?
The intention should not be to make even the sloppiest assignment convert to my constraints. The intention should be to inform the assignee that he violates my constraints.
Here are some goodies:
classdef SomeClass
properties
x (1,4) double
end
end
>> obj = SomeClass
obj =
SomeClass with properties:
x: [0 0 0 0]
>> obj.x = 2
obj =
SomeClass with properties:
x: [2 2 2 2]
>> obj.x = "a"
obj =
SomeClass with properties:
x: [NaN NaN NaN NaN]
>> obj.x = "0"
obj =
SomeClass with properties:
x: [0 0 0 0]
>> obj.x = '0'
obj =
SomeClass with properties:
x: [48 48 48 48]
>> obj.x = '01'
Error setting property 'x' of class 'SomeClass':
Size of value must match specified dimensions 1×4 or be scalar.

Sign in to comment.


Florian Osterloh
Florian Osterloh on 12 Feb 2020
Thank you for your answers. @Steven Lord, yes I already know this from the documentation. I put the example to point out that it can be problematic to have both specified, class and validatorFunction. I know that I must not use the class specification but a validatorFunction to get my desired restriction. I can write own ValidatorFunctions or own classes that cannot be converted. But a very smart readable soloution for me, without having to add much more code, or having to check that nobody is using the class specification, would be exactly this instad a 'coercive conversion' a 'class validation'. But I guess as @Sean de Wolski already mentioned this is not possible.

  0 Comments

Sign in to comment.

Sign in to answer this question.