MATLAB Answers

0

Restricting method access to classes, NOT methods of classes

Asked by D. Plotnick on 20 Jul 2018
Latest activity Commented on by D. Plotnick on 23 Jul 2018
Hello all,
I am trying to understand some method access capabilities, so that methods can only my accessed by objects of a certain class, NOT one of its subclasses. I had thought that this restriction could be done using (Access = private), but that seems to restrict any external calls to the method, NOT calls by objects belonging to the subclass. I also don't see (Access = ?className) working, since an object of the subclass will also belong to the current class.
If the above made sense, and you can help, great! If not, below is a more practical example.
I am attempting to solve the following type of problem. I have a hierarchy of classes and subclasses, and I want to determine the lowest level of this hierarchy that a given object might belong to. As a thought example: I have phylogeny classes in the class hierarchy:
life=>animals=>vertebrates=>mammals,
with numerous other branchings. I have some object with a number of properties, and at each level of the hierarchy I have methods that check whether we have enough information to classify the object to a lower level (such as looking for hasSpine and makesMilk). At some point, we may simply run out of information (filled properties) to further classify our object, so it may be stuck as a 'vertebrates' class object, rather than the lowest level 'mammals'.
In order to do this check, I am storing a list of subclasses in each class. The current class hands each listed subclass in turn all of the available properties, and subclass methods then determine whether the current class is a member of that subclass. If it is, the object is recast as that subclass. This procedure is then repeated until either we run out of branches to head down, or no branch reports that the object is a member (let's ignore multiple branches saying the object is a member, for now).
OK. So with the above story, I want to prevent 'vertebrates' objects from calling certain 'animals' methods, namely the method that asks "what are the subclasses I need to check". At the moment, I am stuck in a loop with one of two issues; either,
  • I have no method defined at the sub-class level to overload the super-class methods. The object thus calls the super-class method for getSubclasses and winds up in a horrible loop (since it is checking the same subclasses again and again, and we already know the object is a member of at least one).
  • I tried (Access = private), but that also blocks s = getSubclasses(obj) from working, since I am not calling the method with another method of that class, but with the object itself as the argument.
Now, there are some kludgey workarounds I can imagine: making sure I overload the super-class methods at EVERY level of the hierarchy, some more advanced use of 'isa' to make sure the object does NOT belong to one of the subclasses listed, etc. But I think there should be a way of doing this using access properties. Is there?
Cheers, -Dan

  0 Comments

Sign in to comment.

1 Answer

Answer by Steven Lord
on 20 Jul 2018
 Accepted Answer

I am storing a list of subclasses in each class.
That makes your system tightly coupled and seems like it's going to cause you to have to do a LOT of work if you add a new lowest-level class. You're going to need to touch ALL its superclasses.
I want to prevent 'vertebrates' objects from calling certain 'animals' methods
This is a violation of the Liskov substitution principle.
I think instead you should consider using the Factory method design pattern. Encapsulating the logic to determine the lowest level class that can represent the object in question in one factory function instead of having it scattered through the class hierarchy will hopefully reduce the number of places you need to modify code when adding / removing / modifying a class in your hierarchy.
You may even be able to use the introspection and metadata capabilities to help automate some of the decision making (if you have a list of all the classes in your hierarchy, because they are in a directory on which you can call dir or are in a package, you can find which of those classes has a Constant property hasSpine with a default value of true AND a Constant property makesMilk with a default value of true.)
Note that I haven't fully designed this, but I think you should be able to use meta.class, meta.property, and findobj to achieve what you want.

  3 Comments

Thanks! These are all helpful ideas, most of which I hadn't heard of before. Looks like I have some reading ahead of me.
With regards to your first point, I was actually only doing this in a one-generation-down sense, where each class was only aware of its immediate subclasses. That way, I could add in new subclasses and only modify the immediate superclass. The goal, using the previous thought experiment, was to enable more easily adding new branches to the class hierarchy, such as "installing" the branch of classes Arthropoda under the Animals superclass.
The hope was to create some object of lets say class Giraffe, and have it not need to carry around a hardcoded list of all of its superclasses in an object property. All Giraffes are Mammals => are Animals => are Life. Sounds like the factory method may indeed be what I am looking for.
"All Giraffes are Mammals => are Animals => are Life."
Normally that gets handled by inheritance automatically rather than having each subclass keep an explicit list of its superclasses.
classdef Mammal < Animal
end
classdef Animal < Life
end
classdef Life
end
classdef Fish < Animal
end
Now you can check with isa:
Giraffe = Mammal();
isa(Giraffe, 'Mammal') % true
isa(Giraffe, 'Animal') % true
isa(Giraffe, 'Life') % true
isa(Giraffe, 'Fish') % false
Yep, that's exactly what I was going for. But that's what then got me in trouble with the substitution issue, and calling superclass methods. I essentially wanted to hand some base superclass a bunch of taxonomic information, and based on both what information is provided (which object properties are filled), and what those poperty values were, recast the initial object as the lowest level class possible in the hierarchy. That way I could subsequently use 'isa' to determine execution in other functions. I would also use method inheritance for appropriate methods: the methods birth and death could be inherited from the Life class.
The issue I am still working with is not the general concepts of classdef and inheritance, but rather the more abstract issues of constructing the class hierarchy itself, and then determining which class in the hierarchy an object should be cast as. Do I want a top level object or method that know's the hierarchy in its entirety, or do I want each class in the hierarchy to know its parent-child links, or a hybrid where a method can assemble the hierarchy by reading in all of those links available in some +stuffClasses package that contains all of my current classes? Does the object I am instantiating figure out its class on its own, or using methods within the hierarchy.
I just picked up a copy of Gamma et al. 's Design patterns book, since I was totally unfamiliar with much of the theory. At least as of the end of Chapter 1, it sounds like factory method is indeed what I want.

Sign in to comment.