Sixometer++

chromatic on 2008-12-13T09:28:42

Want more fun with bleadperl? Gisle wanted class blocks wrapped in implicit BEGIN blocks and asked for inheritance, which I already planned to do anyway.

Andy Wardley wondered if the syntax breaks existing code. There's only one place where it might: if you've defined your own class subroutine with a CODE prototype as its first argument. Note especially that there is no problem with is, even though I've borrowed that syntax.

use Test::More tests => 9;

{
    class Foo;

    sub new { bless {}, shift }
    sub WHO { 'foo' }
    sub FOO { 'FOO' }
}

class Bar {
    sub new { bless {}, shift }
    sub WHO { 'bar' }

    ::is( __PACKAGE__, 'Bar',
        'class name block should set package name in block'  );

    class Bar::Baz is Bar is Foo {
        sub WHO { 'baz' }
    }

    ::is( __PACKAGE__, 'Bar',
        '... and should stay set'  );
}


# use the prototyped is() proves that C doesn't break old code
is __PACKAGE__, 'main', 'class name should not leak out of block';

my $foo = Foo->new();
my $bar = Bar->new();
my $baz = Bar::Baz->new();

is( $foo->isa( 'Foo' ), 1, 'Foo constructor should work' );
is( $foo->WHO(), 'foo', '... in the right package' );
is( $bar->isa( 'Bar' ), 1, 'Bar constructor should work' );
is( $bar->WHO(), 'bar', '... in the right package' );
is( $baz->isa( 'Bar::Baz' ), 1, 'Class inheritance should work' );
is( $baz->WHO(), 'baz', '... in the right package' );
is( $baz->FOO(), 'FOO', '... and multiple inheritance should work' );

Steve Peters suggested disabling this feature by default, unless users enable it with use feature 'class'; or use 5.012;, but where's the fun in that?


sub new

sartak on 2009-01-29T23:41:16

I think a default implementation for new would be a useful addition to class. How's this?

sub new {
    my $class = shift;
    my %args  = @_;

    return bless \%args, $class;
}

You could go further and implement something akin to Moose's BUILD, BUILDALL, and BUILDARGS.