Inheritance, Method Resolution and UNIVERSAL

package Animal;
use v5.36;
sub new($class, %args) { bless { name => $args{name}, sound => 'generic noise' }, $class }
sub name($self)  { $self->{name} }
sub speak($self) { sprintf '%s says %s', $self->name, $self->sound }
sub sound($self) { $self->{sound} }

package Dog;
use v5.36;
use parent -norequire, 'Animal';      # sets @ISA (use -norequire when the parent is in the same file)

sub new($class, %args) {
    my $self = $class->SUPER::new(%args);    # call the parent constructor
    $self->{tricks} = $args{tricks} // [];
    return $self;
}
sub sound($self) { 'Woof' }           # override
sub speak($self) {
    my $base = $self->SUPER::speak();         # call the parent method
    return "$base!";
}

package main;
my @animals = (Animal->new(name => 'Generic'), Dog->new(name => 'Rex'));
say $_->speak for @animals;           # polymorphism
say Dog->new(name => 'x')->isa('Animal') ? 'is an Animal' : 'no';
say 'can speak' if Dog->can('speak');
my $code = Dog->can('sound'); say $code->(Dog->new);   # can returns a code ref
say Dog->VERSION // 'no version';
say 'DOES role' if $obj->DOES('Some::Role');

28.1 Method Resolution Order

@ISA lists parent classes. Perl supports multiple inheritance.

The default MRO is depth-first, left-to-right (DFS). Use use mro 'c3'; for C3 linearization (consistent with Python), and next::method instead of SUPER:: in diamond hierarchies.

package D; use mro 'c3'; use parent -norequire, 'Left', 'Right';   # Left and Right both inherit from a common base
sub hello($self) { 'D ' . $self->next::method() }
say join ', ', @{ mro::get_linear_isa('D') };

28.2 UNIVERSAL Methods

Is the object a member of the class or a subclass? (Prefer the isa operator: $obj isa Class) Returns a code ref if the method exists Role check (defaults to isa)

Returns the version / dies if lower than $min