use strict; $^W++; use Class::Prototyped qw(:EZACCESS); use Data::Dumper; use Test; BEGIN { $|++; plan tests => 12 } $Data::Dumper::Sortkeys = 1; $Data::Dumper::Sortkeys = 1; my $record = ''; package MyClass; @MyClass::ISA = qw(Class::Prototyped); sub DESTROY { $record .= "You are in MyClass::DESTROY for " . ref($_[0]) . "\n"; } package MyClass_Alt; @MyClass_Alt::ISA = qw(Class::Prototyped); sub DESTROY { $record .= "You are in MyClass_Alt::DESTROY for " . ref($_[0]) . "\n"; } package main; my $name1; my $name2; my $name3; # This demonstrates normal destruction. { my $foo = MyClass->new( 'destroy!' => sub { $record .= "You are in the objects destroy.\n"; $_[0]->super('destroy'); $record .= "Just called super-destroy.\n"; }, ); $name1 = ref($foo); } ok( $record, <new( 'destroy!' => sub { $record .= "p2 before super for " . ref($_[0]) . "\n"; $_[0]->super('destroy'); $record .= "p2 after super for " . ref($_[0]) . "\n"; }, ); $name2 = ref($p2); { my $p1 = MyClass->new( 'destroy!' => sub { $record .= "p1 before super for " . ref($_[0]) . "\n"; $_[0]->super('destroy'); $record .= "p1 after super for " . ref($_[0]) . "\n"; }, ); $name1 = ref($p1); $p2->addSlot('p1' => $p1); } } ok( $record, <new( 'destroy!' => sub { $record .= "p2 before super for " . ref($_[0]) . "\n"; $_[0]->super('destroy'); $record .= "p2 after super for " . ref($_[0]) . "\n"; }, ); $name2 = ref($p2); { my $p1 = MyClass->new( 'destroy!' => sub { $record .= "p1 before super for " . ref($_[0]) . "\n"; $_[0]->super('destroy'); $record .= "p1 after super for " . ref($_[0]) . "\n"; }, ); $name1 = ref($p1); $p2->addSlot('parent*' => $p1); } } ok( $record, <new( 'destroy!' => sub { $record .= "p3 before super for " . ref($_[0]) . "\n"; $_[0]->super('destroy'); $record .= "p3 after super for " . ref($_[0]) . "\n"; }, ); $name3 = ref($p3); { my $p2 = MyClass->new( 'destroy!' => sub { $record .= "p2 before super for " . ref($_[0]) . "\n"; $_[0]->super('destroy'); $record .= "p2 after super for " . ref($_[0]) . "\n"; }, ); $name2 = ref($p2); { my $p1 = MyClass->new( 'destroy!' => sub { $record .= "p1 before super for " . ref($_[0]) . "\n"; $_[0]->super('destroy'); $record .= "p1 after super for " . ref($_[0]) . "\n"; }, ); $name1 = ref($p1); $p2->addSlot('p1' => $p1); $p3->addSlot('p1' => $p1); } } } ok( $record, <new( 'destroy!' => sub { $record .= "p3 before super for " . ref($_[0]) . "\n"; $_[0]->super('destroy'); $record .= "p3 after super for " . ref($_[0]) . "\n"; }, ); $name3 = ref($p3); { my $p2 = MyClass->new( 'destroy!' => sub { $record .= "p2 before super for " . ref($_[0]) . "\n"; $_[0]->super('destroy'); $record .= "p2 after super for " . ref($_[0]) . "\n"; }, ); $name2 = ref($p2); { my $p1 = MyClass->new( 'destroy!' => sub { $record .= "p1 before super for " . ref($_[0]) . "\n"; $_[0]->super('destroy'); $record .= "p1 after super for " . ref($_[0]) . "\n"; }, ); $name1 = ref($p1); $p2->addSlot('parent*' => $p1); $p3->addSlot('parent*' => $p1); } } } ok( $record, <new( 'destroy!' => sub { $record .= "p2 before super for " . ref($_[0]) . "\n"; $_[0]->super('destroy'); $record .= "p2 after super for " . ref($_[0]) . "\n"; }, ); $name2 = ref($p2); { my $p1 = MyClass->new( 'destroy!' => sub { $record .= "p1 before super for " . ref($_[0]) . "\n"; $_[0]->super('destroy'); $record .= "p1 after super for " . ref($_[0]) . "\n"; }, ); $name1 = ref($p1); $p2->addSlot([qw(parent* promote)] => $p1); } } ok( $record, <new( 'destroy!' => sub { $record .= "p2 before super for " . ref($_[0]) . "\n"; $_[0]->super('destroy'); $record .= "p2 after super for " . ref($_[0]) . "\n"; }, ); $name2 = ref($p2); { my $p1 = MyClass->new( 'destroy!' => sub { $record .= "p1 before super for " . ref($_[0]) . "\n"; $_[0]->super('destroy'); $record .= "p1 after super for " . ref($_[0]) . "\n"; }, ); $name1 = ref($p1); $p2->addSlot('parent*' => $p1); } } ok( $record, <new( 'destroy!' => sub { $record .= "p3 before super for " . ref($_[0]) . "\n"; $_[0]->super('destroy'); $record .= "p3 after super for " . ref($_[0]) . "\n"; }, ); $name3 = ref($p3); { my $p2 = MyClass->new( 'destroy!' => sub { $record .= "p2 before super for " . ref($_[0]) . "\n"; $_[0]->super('destroy'); $record .= "p2 after super for " . ref($_[0]) . "\n"; }, ); $name2 = ref($p2); { my $p1 = MyClass->new( 'destroy!' => sub { $record .= "p1 before super for " . ref($_[0]) . "\n"; $_[0]->super('destroy'); $record .= "p1 after super for " . ref($_[0]) . "\n"; }, ); $name1 = ref($p1); $p2->addSlot([qw(parent* promote)] => $p1); $p3->addSlot([qw(parent* promote)] => $p1); } } } ok( $record, <new( 'destroy!' => sub { $record .= "p3 before super for " . ref($_[0]) . "\n"; $_[0]->super('destroy'); $record .= "p3 after super for " . ref($_[0]) . "\n"; }, ); $name3 = ref($p3); { my $p2 = MyClass->new( 'destroy!' => sub { $record .= "p2 before super for " . ref($_[0]) . "\n"; $_[0]->super('destroy'); $record .= "p2 after super for " . ref($_[0]) . "\n"; }, ); $name2 = ref($p2); $p3->addSlot([qw(parent* promote)] => $p2); { my $p1 = MyClass->new( 'destroy!' => sub { $record .= "p1 before super for " . ref($_[0]) . "\n"; $_[0]->super('destroy'); $record .= "p1 after super for " . ref($_[0]) . "\n"; }, ); $name1 = ref($p1); $p2->addSlot([qw(parent* promote)] => $p1); } } } ok( $record, <new( 'destroy!' => sub { $record .= "p3 before super for " . ref($_[0]) . "\n"; $_[0]->super('destroy'); $record .= "p3 after super for " . ref($_[0]) . "\n"; }, ); $name3 = ref($p3); { my $p2 = MyClass->new( 'destroy!' => sub { $record .= "p2 before super for " . ref($_[0]) . "\n"; $_[0]->super('destroy'); $record .= "p2 after super for " . ref($_[0]) . "\n"; }, ); $name2 = ref($p2); $p3->addSlot('parent2**' => $p2); { my $p1 = MyClass_Alt->new( 'destroy!' => sub { $record .= "p1 before super for " . ref($_[0]) . "\n"; $_[0]->super('destroy'); $record .= "p1 after super for " . ref($_[0]) . "\n"; }, ); $name1 = ref($p1); $p3->addSlot('parent1**' => $p1); } } } ok( $record, <new( 'destroy!' => sub { $record .= "p3 before super for " . ref($_[0]) . "\n"; $_[0]->super('destroy'); $record .= "p3 after super for " . ref($_[0]) . "\n"; }, ); $name3 = ref($p3); { my $p2 = MyClass->new( 'destroy!' => sub { $record .= "p2 before super for " . ref($_[0]) . "\n"; $_[0]->super('destroy'); $record .= "p2 after super for " . ref($_[0]) . "\n"; }, ); $name2 = ref($p2); $p3->addSlot('parent2**' => $p2); { my $p1 = Class::Prototyped->new( 'destroy!' => sub { $record .= "p1 before super for " . ref($_[0]) . "\n"; $_[0]->super('destroy'); $record .= "p1 after super for " . ref($_[0]) . "\n"; }, ); $name1 = ref($p1); $p3->addSlot('parent1**' => $p1); } } } ok( $record, <new( name => 'p1', count => 0, ); my $ref = ref($p1); $p1->addSlots( 'new!' => sub { my $self = $_[0]->super('new', 'parent*' => @_); $self->count($self->count()+1); $record .= "Incremented count to " . $self->count . " using " . ref($self) . " from new called on " . ref($_[0]) . "\n"; return $self; }, 'destroy!' => sub { if (ref($_[0]) eq $ref) { $record .= "p1::destroy called on self with a count of " . $_[0]->count . "\n"; } else { $record .= "p1::destroy called on " . $_[0]->name() . " (" . ref($_[0]) . ")\n"; $_[0]->count($_[0]->count()-1); $record .= "Decremented count to " . $_[0]->count . "\n"; } }, ); } $name1 = ref($p1); $p2 = $p1->new(name => 'p2'); $name2 = ref($p2); $p3 = $p2->new(name => 'p3'); $name3 = ref($p3); } } } ok( $record, <