Using narrower property validation definitions in subclasses + using an abstract class for property validation
Show older comments
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 Comments
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
on 5 Apr 2021
Accepted Answer
More Answers (0)
Categories
Find more on Events in Help Center and File Exchange
Community Treasure Hunt
Find the treasures in MATLAB Central and discover how the community can help you!
Start Hunting!