0

I have some classes that I created a couple of constant properties for. Here is some example code:

classdef genericClassName < handle
    properties (Constant)
        Name = 'genericClassName'
        Description = 'description of the class'
    end
...

In the main code I create objects by assigning the class handle, which in this case comes from a pre-assigned value delivered from a separate function. It would be like

fuctionModel = @genericClassName;

and later I'll create other objects and pass the value of functionModel to those classes. Up to this point, it all works fine.

The Matlab documentation says that these constant properties are accessed like this:

genericClassName.Name
genericClassName.Description

I can type that into the command line and it produces the desired result, giving the value of the Name or Description property - the same values assigned to the constant properties. However, I only have the handle, which is saved in functionModel as @genericClassName.

This is my question: How can I refer to this class and its constant properties when I only have the handle, with its at-sign prepended?

Update Short of a simpler or concise answer, a combination of the answers from @Edric and @CrisLuengo seems to work. For instance:

mc=meta.class.fromName(func2str(functionalModel));
result = eval([mc.Name '.Description']);

puts the constant with the name Description into the variable result. This is usable for what I need, and I'll probably just wrap it into a function.

Jim
  • 5,940
  • 9
  • 44
  • 91
  • If you're going to do that, just do `eval([func2str(functionalModel),'.Description'])`. Now you're getting the class description from the name, and only using that description to get the name, which seems rather silly. – Cris Luengo Mar 16 '21 at 19:49
  • It’s not just about the name, Cris. These are just examples – Jim Mar 16 '21 at 19:51
  • What I meant is that if you're not going to use `mc.PropertyList`, don't get `mc`. `mc.Name` is exactly the string that you put into `mc=meta.class.fromName(...)`. The code you added to your question is very redundant. Also, please post it as an answer, questions should not include an answer. You can accept your own answer if you like. – Cris Luengo Mar 16 '21 at 19:53
  • Just reread your comment. Yes, the meta.class is not needed. The func2str extracts what I was looking for. – Jim Mar 17 '21 at 16:20

3 Answers3

3

Hm, if you have only a handle to the constructor method, and you wish to avoid constructing an instance (MATLAB allows you to access Constant properties from instances), then here's a way you can do it using meta.class.fromName.

fh = @genericClassName;
% Get the metaclass from the constructor
mc = meta.class.fromName(func2str(fh));
% Find the property named 'Name'
idx = strmatch('Name', {mc.PropertyList.Name})
% Get the default (Constant) value
mc.PropertyList(idx).DefaultValue
Edric
  • 23,676
  • 2
  • 38
  • 40
  • Thanks, Edric. This is interesting. But the *Name* and *Description* properties are assigned constants within the class definition. Unfortunately, these are the same labels of meta-properties. Of course the meta property *Name* will meet my immediate need. The meta property *Description* is described as "currently not used" in the meta.class class documentation. – Jim Mar 16 '21 at 19:04
  • Not sure I understand the problem. The `meta.class` property "Description" is unrelated to the Constant "Description" property of your class, it just happens to have the same name. You can extract the Constant value of _any_ property using the pattern above by replacing the name in the `strmatch` expression, i.e. `dIdx = strmatch('Description', {mc.PropertyList.Name})` – Edric Mar 17 '21 at 08:12
2

There is no such thing as a class handle. I don’t think there is a way in MATLAB to reference a class other than through its name (either directly in code or as a string). Your code

fuctionModel = @genericClassName;

stores a handle to the constructor genericClassName in the variable fuctionModel. With this handle, you can construct objects of your class, but you cannot do anything else. This is not a reference to the class itself.

It is unclear why you have set up your code this way. However, the easiest way to access your constants through this handle is to first create an object of your class:

a = fuctionModel();
a.Name

Edric suggests an alternative, also not convenient or pretty.

A third alternative, which I’m not advocating for (this can cause slowdown in your code, and is hard to read and thus maintain) is to store the name of your class as a string, then use eval to get your value:

fuctionModel = 'genericClassName';
eval([fuctionModel,'.Name']);
Cris Luengo
  • 55,762
  • 10
  • 62
  • 120
  • I added a link to the Matlab documentation I referred to. (I should have put that in the first place.) It definitely shows that constants defined within a class can be accessed by the classname-dot-propertyname method. My question isn't about accessing constants this way. It's about how to reference the class when I have the name of the class prefixed with an "@" and acheive the same objective - to get the value of the named constant property. – Jim Mar 16 '21 at 06:57
  • BTW, the reason I am trying to do this is in line with being Pythonic. I believe this is possible in Python and I'd like to do the same thing here for the benefit of the people who are paying me. – Jim Mar 16 '21 at 07:03
  • @rahnema1: probably, yes. Thanks for pointing that out! – Cris Luengo Mar 16 '21 at 13:53
  • @Jim: please read my answer more carefully. You cannot reference a class, I don’t think this is possible at all in MATLAB. What you have is the handle to its constructor. Function handles reference only functions, nothing else. – Cris Luengo Mar 16 '21 at 13:55
  • @Jim: I've been thinking about your use case. If you want to pass this class reference only to pass a set of constants, then you could instead create a function that returns a struct, something like `function data=foo, data=struct('Name','name','X',10);`. Constants in MATLAB have traditionally been functions, for example `pi` is a function. Since the last few MATLAB releases, you can now do `foo.Name`. And this would be perfectly compatible with your handle: `f=@foo; f().Name`. – Cris Luengo Mar 16 '21 at 16:44
0

Short of a simpler or concise answer, a combination of the answers from @Edric and @CrisLuengo seems to work. For instance:

mc=meta.class.fromName(func2str(functionalModel));
result = eval([mc.Name '.Description']);

puts the constant with the name Description into the variable result. This works well enough when wrapped in a function.

Jim
  • 5,940
  • 9
  • 44
  • 91