Using narrower property validation definitions in subclasses + using an abstract class for property validation
Ältere Kommentare anzeigen
Hello,
BLUF: It is not clear to me why I can overload methods, but not property validation/class assertions, in subclasses.
I'll lead off by saying that I don't believe what I want to do right now is possible in Matlab 2021a. I do want to know:
- Is there a best practices workaround
- Is there a good reason it isn't supported
- Is this something we should get into the feature request pipeline
Let's start with a refrigerator analogy; I initially want to create an abstract superclass called container, that has a bunch of methods for e.g. adding contents, removing contents, and checking whether the container is full.
classdef (Abstract) container < handle
properties (Abstract)
contents
capacity
end
methods
tf = addContent(this,content) % e.g. add a brownie to the top of the stack, return false if the container is full
content = rmContent(this) % e.g. take a brownie off the top of the stack
tf = isFull % return true if numel(contents) == capacity
end
end
Now, let's say I want to make a specific container that can hold eggs. Seems simple enough, and I can even overload the rmContent so that I can grab a specific egg, rather than the top of the stack. I am also going to make an abstract class called "eggShapedItems", since my container could hold chicken eggs, cadbury eggs, easter eggs, etc. I will also make a concrete egg class
classdef eggCarton < container
properties
contents eggShapedItem
capacity = 12
end
methods
content = rmContent(this,index)
end
end
classdef (Abstract) eggShapedItem < matlab.mixin.heterogeneous
end
classdef chickenEgg < eggShapedItem
end
I have gone with heterogeneous so that my container can hold a mixed array of eggShapedItems.
But oh no! I immediately have a problem instantiating an eggCarton: "Using size and validation functions on an inherited property is not supported. Property 'contents' is defined as abstract property in superclass 'container".
Hmm, what if I change contents to concrete in the superclass:
classdef (Abstract) container < handle
properties
contents
end
end
New error: "Cannot define property 'contents' in class 'eggCarton' because the property has already been defined in the superclass 'container'"
In other words, while I can overload methods in the subclass, I cannot overload properties (or their validation).
Ok...so I can get around this by not defining the property contents at all in the superclass 'container' I am not happy about this for two reasons***: ***(there is another issue, see at bottom)
- The concrete methods of 'container' still assume that there is in fact a property called 'contents', even if it isn't defined in the superclass. I want these methods to be inherited by all containers, and redefining 'contents' in every subclass is bad practice.
- I am blocked from further narrowing the definitions of either 'eggShapedItems' or 'eggCarton'. e.g.:
classdef smallEggCarton < eggCarton
properties
contents smallEggShapedItem
end
end
classdef smallEggShapedItem < eggShapedItem
end
While this may be a goofy example, I think it is clear that there would be utility in being able to progressively overload the property validations through a subclass tree. In this case, I have made each class of 'contents' a subclass of the one used in the superclass; however, there would also be utility in using easily converted classes, e.g.:
classdef eggCarton < container
properties
capacity uint16
end
end
classdef smallEggCarton < eggCarton
properties
capacity uint8
end
end
If we could overload property definitions, onus is then on me to make sure that inherited methods are compatible, or that I overload them in the subclass to be compatible. I can live with that. AFAIK, that is not possible right now; the property definition is locked in by the superclass - only the default value can change, and that only if the property is abstract in the superclass.
Finally, I noted that there is another issue when trying to intantiate an eggCarton: "Error defining property 'contents' of class 'eggCarton'. Class eggShapedItem is abstract. Specify a default value for property contents."
This is a seperate, but also frustrating restriction on the property validation in Matlab; in this example, the contents of my eggCarton must be instances subclassed to 'eggShapedItem', but I would never make a concrete 'eggShapedItem', it should be an Abstract class.
As before, there are workarounds; make eggShapedItem concrete, or remove the class from the property definition entirlley, and move the validation into an overloaded set.contents(this,content) method. Again, there are drawbacks:
- I lose all of the code completion help that comes with defining the property's class in the prop block.
- This also strikes me as sloppy coding
- I could understand the issue if I tried to create an array on instantiation (e.g. contents (12,:) eggShapedItem). and I do get that Matlab is trying to put in an empty (e.g. this.contents = eggShapedItem.empty), which returns an error for abstract classes.
Thanks,
Dan
2 Kommentare
I could understand the issue if I tried to create an array on instantiation (e.g. contents (12,:) eggShapedItem). and I do get that Matlab is trying to put in an empty (e.g. this.contents = eggShapedItem.empty), which returns an error for abstract classes.
That doesn't sound like a drawback. It sounds like you understand why it's not allowed! In any case, a concrete property needs to be able to hold a value at all times, so you have to either specify a default eggShapedItem object or reframe the property validation so as to make an [] value legitimate.
Daniel Plotnick
am 5 Apr. 2021
Akzeptierte Antwort
Weitere Antworten (0)
Kategorien
Mehr zu Events finden Sie in Hilfe-Center und File Exchange
Community Treasure Hunt
Find the treasures in MATLAB Central and discover how the community can help you!
Start Hunting!