Logo Questions Linux Laravel Mysql Ubuntu Git Menu
 

In Moose, how can I tell whether one object's class is a subclass of another object's class?

Suppose I have two objects $obj1 and $obj2 that are both instances of Moose classes. I want to find out which of the following applies:

  • $obj1's class is the same as $obj2's;
  • $obj1's class is a subclass of $obj2's;
  • $obj1's class is a superclass of $obj2's;
  • Neither object's class is a subclass of the other's.

How can I do this?

like image 582
Ryan C. Thompson Avatar asked Dec 09 '22 13:12

Ryan C. Thompson


2 Answers

  1. Is $obj1's class the same as $obj2's?

    ref $obj1 eq ref $obj2;
    
  2. Is $obj1's class a subclass of $obj2's?

    $obj1->isa(ref $obj2);
    
  3. Is $obj1's class a superclass of $obj2's?

    $obj2->isa(ref $obj1);
    
  4. Neither object's class is a subclass of the other's.

    See above.

Update:

In response to comments regarding roles applied at run time:

package My::X;

use Moose; use namespace::autoclean;

sub boo { }

__PACKAGE__->meta->make_immutable;

package My::Y;

use Moose; use namespace::autoclean;

extends 'My::X';

__PACKAGE__->meta->make_immutable;

package My::Z;

use Moose::Role; use namespace::autoclean;

requires 'boo';

package main;

use Test::More tests => 2;

use Moose::Util qw( apply_all_roles );

my $x = My::X->new;
my $y = My::Y->new;

ok($y->isa(ref $x), 'Before role was applied at runtime');

apply_all_roles($x, 'My::Z');

ok($y->isa(ref $x), 'After role was applied at runtime');

Output:

1..2
ok 1 - Before role was applied at runtime
not ok 2 - After role was applied at runtime
#   Failed test 'After role was applied at runtime' at C:\Temp\t.pl line 36.
# Looks like you failed 1 test of 2.
like image 87
Sinan Ünür Avatar answered May 09 '23 15:05

Sinan Ünür


Using the Class::MOP underpinnings in Moose you can introspect all this information.

For eg:

{
    package Daddy;
    use Moose;
}

{
    package Kid;
    use Moose;
    extends 'Daddy';
}

my $son      = Kid->new;
my $daughter = Kid->new;

my $sons_class                  = ($son->meta->class_precedence_list)[0];
my $daughters_class             = ($daughter->meta->class_precedence_list)[0];

my @sons_subclasses             = $son->meta->subclasses;     # or better...
my @daughters_subclasses        = $daughter->meta->direct_subclasses;

my @sons_superclasses           = $son->meta->superclasses;

my @Daddies_children            = Daddy->meta->direct_subclasses;

Also see this SO question/answer How can I find all the packages that inherit from a package in Perl?

/I3az/

like image 34
draegtun Avatar answered May 09 '23 13:05

draegtun