Static class call via string variable

9 Ansichten (letzte 30 Tage)
Jim Hokanson
Jim Hokanson am 27 Apr. 2013
Bearbeitet: Cedric am 17 Okt. 2017
Is it possible to call a static method or Constant property from a class whose name is represented by a string without using eval?
my_class_string = 'my_class'
eval([my_class_string '.MY_CONSTANT_PROPERTY'])
  1 Kommentar
Daniel Shub
Daniel Shub am 28 Apr. 2013
At the point in which it is a string it might, and probably is, too late. How do you end up with a string and not an object?

Melden Sie sich an, um zu kommentieren.

Akzeptierte Antwort

Matt J
Matt J am 28 Apr. 2013
Bearbeitet: Matt J am 28 Apr. 2013
Here's a way to access a constant property without creating an object of the class.
mc=meta.class.fromName('myclass');
mp=mc.PropertyList;
[~,loc]=ismember('MY_CONSTANT_PROPERTY',{mp.Name});
propertyValue = mp(loc).DefaultValue;
For a static method, I don't know why you wouldn't use EVAL, but note that you could use FEVAL as well, if it feels better,
out = feval('myclass.MY_STATIC_METHOD');
  3 Kommentare
Matt J
Matt J am 28 Apr. 2013
Bearbeitet: Matt J am 28 Apr. 2013
The property solution is awful, but I suspect it is probably the only way to accomplish what I was looking for
Awful because of the code complexity? I wouldn't agree with that as a criticism. You can always hide the lines of code inside an mfile function of your own making.
However, I tend to agree with Daniel that your situation is already awful, needing to work with dynamic classnames and not objects... or at least "awfully peculiar" ;)
I also feel like eval slows down the optimization just a bit (not tested)
No need to test it. It's well known...
Adam
Adam am 15 Okt. 2015
Bearbeitet: Adam am 15 Okt. 2015
This solution works ideally for what I want, which is the same thing essentially and I have used meta class stuff in my code before so I have no aversion to the method, unlike eval!
Since the question did come up as to reasons for wanting this, I thought I would add mine:
I have a bunch of classes representing units in different domains ( e.g. Seconds, MetresPerSecond, KilogramsPerCubicMetre). Each class has a static map property listing supported units (keys being strings like 'm/s', values being function handles to the specific class constructor).
When I read data files I want to interpret the unit string of the data which may come from any one of the domains I define (e.g. TimeUnit, DepthUnit, DensityUnit), but currently only a specific domain object can take a string and convert it into the right unit class object.
So my intention was to write a function that finds all the different types of domain unit in a folder and concatenate all their supported units maps so that I can create a unit class from a string without having to know the domain of the unit a priori.
I'm not 100% sure this is the best solution, but it would allow extension to new unit domains without having to keep updating some hard coded list of these from which the full map of units is created.

Melden Sie sich an, um zu kommentieren.

Weitere Antworten (2)

per isakson
per isakson am 27 Apr. 2013
Bearbeitet: per isakson am 27 Apr. 2013
It's without eval
foo = str2func( my_class_string );
obj = foo();
obj.MY_CONSTANT_PROPERTY
ans =
17
where
classdef my_class
properties ( Constant = true )
MY_CONSTANT_PROPERTY = 17
end
end
An alternative
obj = feval( 'my_class' )
obj.MY_CONSTANT_PROPERTY
But, is it any better than eval? And it does neither depend on static nor constant.
  4 Kommentare
Jim Hokanson
Jim Hokanson am 17 Okt. 2017
That's a good point. Although if you require inputs for valid construction this might lead to confusion later when no inputs were passed in and the nargin check made it seem like that was ok. Like I said in the end Matt is probably right and if used somewhat frequently the ugliness should just be wrapped into a function :/
Cedric
Cedric am 17 Okt. 2017
Bearbeitet: Cedric am 17 Okt. 2017
I sympathize! ;)
I am increasingly implementing more complex constructors that manage special cases though, e.g.
methods
function obj = Xyz( x, y, varargin )
% x must be a num array, yet ..
if ischar( x ) && strcmpi( x, 'test' )
do something
return
end
assert( isnumeric(x), '...' ) ;
assert( isnumeric(y), '...' ) ;
if ~isempty( varargin )
parser = inputParser ;
% .. more lengthy parsing, but no parser if not necessary
end
...

Melden Sie sich an, um zu kommentieren.


Cedric
Cedric am 27 Apr. 2013
Bearbeitet: Cedric am 27 Apr. 2013
Yes, you can proceed the same way as with dynamic field names:
myObject = myClass() ;
methodName = 'foo' ;
x = myObject.(methodName)(arg1, arg2) ;
  1 Kommentar
Jim Hokanson
Jim Hokanson am 27 Apr. 2013
The question is when the class name is dynamic, not the method or property. Thanks though.

Melden Sie sich an, um zu kommentieren.

Kategorien

Mehr zu Construct and Work with Object Arrays finden Sie in Help Center und File Exchange

Community Treasure Hunt

Find the treasures in MATLAB Central and discover how the community can help you!

Start Hunting!

Translated by