Logo Questions Linux Laravel Mysql Ubuntu Git Menu
 

Introspection: how do we get the name of a class within a class?

Say we have

class Foo {}

Is there a way to obtain "Foo" from within the class?

like image 774
jjmerelo Avatar asked May 12 '19 07:05

jjmerelo


2 Answers

Yes.

class Foo {
    say ::?CLASS.^name; # OUTPUT: Foo
}
like image 114
Kaiepi Avatar answered Nov 01 '22 00:11

Kaiepi


Kaiepi's solution has its place, which I'll get to below, but also consider:

class Foo {
    say Foo.perl;         # Foo
    say OUR.WHO;          # Foo
    ::?PACKAGE
}

Foo.perl

This provides a simple answer to your literal question (though it ignores what you're really after, as explained in your comment below and as suggested by the metaprogramming tag and your use of the word "introspection").

OUR.WHO

I think this is typically more appropriate than ::?CLASS.^name for several reasons:

  • Looks less line-noisy.

  • Works for all forms of package, i.e. ones declared with the built in declarators package, module, grammar, or role as well as class, and also custom declarators like actor, monitor, etc.

  • Will lead readers to mostly directly pertinent issues if they investigate OUR and/or .WHO in contrast to mostly distracting arcana if they investigate the ::?... construct.

::?CLASS vs ::?PACKAGE

OUR.WHO only works in a value grammatical slot, not a type grammatical slot. For the latter you need a suitable ::?... form, eg:

class Foo { has ::?CLASS $bar }

And these ::?... forms also work as values:

class Foo { has $bar = ::?CLASS }

So, despite their relative ugliness, they're more general in this particular sense. That said, if generality is at a premium then ::?PACKAGE goes one better because it works for all forms of package.

like image 38
raiph Avatar answered Oct 31 '22 22:10

raiph