Mercurial > pub > Impl
comparison Lib/IMPL/Object.pm @ 2:78cd38551534
in develop
| author | Sergey |
|---|---|
| date | Mon, 10 Aug 2009 17:39:08 +0400 |
| parents | 03e58a454b20 |
| children | e59f44f75f20 |
comparison
equal
deleted
inserted
replaced
| 1:3b418b134d8c | 2:78cd38551534 |
|---|---|
| 1 package IMPL::Object; | 1 package IMPL::Object; |
| 2 use strict; | 2 use strict; |
| 3 | 3 |
| 4 use base qw(IMPL::Class::Meta); | 4 use base qw(IMPL::Object::Abstract); |
| 5 | |
| 6 our $MemoryLeakProtection; | |
| 7 my $Cleanup = 0; | |
| 8 our $Debug; | |
| 9 our %leaked_objects; | |
| 10 | |
| 11 my %cacheCTOR; | |
| 12 | |
| 13 | |
| 14 sub new { | |
| 15 my $class = shift; | |
| 16 my $self = bless {}, ref($class) || $class; | |
| 17 | |
| 18 $self->$_(@_) foreach @{$cacheCTOR{ref $self} || cache_ctor(ref $self)}; | |
| 19 | |
| 20 $self; | |
| 21 } | |
| 22 my $t = 0; | |
| 23 sub cache_ctor { | |
| 24 my $class = shift; | |
| 25 | |
| 26 no strict 'refs'; | |
| 27 my @sequence; | |
| 28 | |
| 29 my $refCTORS = *{"${class}::CTOR"}{HASH}; | |
| 30 | |
| 31 foreach my $super ( @{"${class}::ISA"} ) { | |
| 32 my $superSequence = $cacheCTOR{$super} || cache_ctor($super); | |
| 33 | |
| 34 my $mapper = $refCTORS ? $refCTORS->{$super} : undef; | |
| 35 if (ref $mapper eq 'CODE') { | |
| 36 if ($mapper == *_pass_throgh_mapper{CODE}) { | |
| 37 push @sequence,@$superSequence; | |
| 38 } else { | |
| 39 push @sequence, sub { | |
| 40 my $this = shift; | |
| 41 $this->$_($mapper->(@_)) foreach @$superSequence; | |
| 42 }; | |
| 43 } | |
| 44 } else { | |
| 45 warn "Unsupported mapper type, in '$class' for the super class '$super'" if $mapper; | |
| 46 push @sequence, sub { | |
| 47 my $this = shift; | |
| 48 $this->$_() foreach @$superSequence; | |
| 49 }; | |
| 50 } | |
| 51 } | |
| 52 | |
| 53 push @sequence, *{"${class}::CTOR"}{CODE} if *{"${class}::CTOR"}{CODE}; | |
| 54 | |
| 55 $cacheCTOR{$class} = \@sequence; | |
| 56 return \@sequence; | |
| 57 } | |
| 58 | |
| 59 sub callCTOR { | |
| 60 my $self = shift; | |
| 61 my $class = ref $self; | |
| 62 | |
| 63 $self->$_(@_) foreach @{$cacheCTOR{$class} || cache_ctor($class)}; | |
| 64 } | |
| 65 | 5 |
| 66 sub surrogate { | 6 sub surrogate { |
| 67 bless {}, ref $_[0] || $_[0]; | 7 bless {}, ref $_[0] || $_[0]; |
| 68 } | 8 } |
| 69 | 9 |
| 70 sub superCTOR { | 10 sub new { |
| 71 my $this = shift; | |
| 72 | |
| 73 warn "The mehod is deprecated, at " . caller; | |
| 74 } | |
| 75 | |
| 76 sub toString { | |
| 77 my $self = shift; | |
| 78 | |
| 79 return (ref $self || $self); | |
| 80 } | |
| 81 | |
| 82 sub DESTROY { | |
| 83 if ($MemoryLeakProtection and $Cleanup) { | |
| 84 my $this = shift; | |
| 85 warn sprintf("Object leaks: %s of type %s %s",$this->can('ToString') ? $this->ToString : $this,ref $this,UNIVERSAL::can($this,'_dump') ? $this->_dump : ''); | |
| 86 } | |
| 87 } | |
| 88 | |
| 89 sub END { | |
| 90 $Cleanup = 1; | |
| 91 $MemoryLeakProtection = 0 unless $Debug; | |
| 92 } | |
| 93 | |
| 94 sub _pass_throgh_mapper { | |
| 95 @_; | |
| 96 } | |
| 97 | |
| 98 sub PassThroughArgs { | |
| 99 my $class = shift; | 11 my $class = shift; |
| 100 $class = ref $class || $class; | 12 my $self = bless {}, ref($class) || $class; |
| 101 no strict 'refs'; | 13 $self->callCTOR(@_); |
| 102 no warnings 'once'; | 14 |
| 103 ${"${class}::CTOR"}{$_} = \&_pass_throgh_mapper foreach @{"${class}::ISA"}; | 15 $self; |
| 104 } | |
| 105 | |
| 106 package self; | |
| 107 | |
| 108 our $AUTOLOAD; | |
| 109 sub AUTOLOAD { | |
| 110 goto &{caller(). substr $AUTOLOAD,4}; | |
| 111 } | |
| 112 | |
| 113 package supercall; | |
| 114 | |
| 115 our $AUTOLOAD; | |
| 116 sub AUTOLOAD { | |
| 117 my $sub; | |
| 118 my $methodName = substr $AUTOLOAD,11; | |
| 119 no strict 'refs'; | |
| 120 $sub = $_->can($methodName) and $sub->(@_) foreach @{caller().'::ISA'}; | |
| 121 } | 16 } |
| 122 | 17 |
| 123 =pod | 18 =pod |
| 124 =h1 SYNOPSIS | 19 =h1 SYNOPSIS |
| 125 | 20 |
| 171 | 66 |
| 172 # will print | 67 # will print |
| 173 # | 68 # |
| 174 # Foo: Mazzi | 69 # Foo: Mazzi |
| 175 # Bar: Fugi | 70 # Bar: Fugi |
| 176 # Foo: | |
| 177 # Bar: | 71 # Bar: |
| 178 # Composite: Hello World! | 72 # Composite: Hello World! |
| 179 | 73 |
| 180 =h1 Description | 74 =h1 Description |
| 181 Базовый класс для объектов. Реализует множественное наследование | 75 Базовый класс для объектов, основанных на хеше. |
| 182 | |
| 183 | 76 |
| 184 =h1 Members | 77 =h1 Members |
| 78 | |
| 79 =level 4 | |
| 80 | |
| 81 =item operator C<new>(@args) | |
| 82 | |
| 83 Создает экземпляр объекта и вызывает конструктор с параметрами @args. | |
| 84 | |
| 85 =item operator C<surrogate>() | |
| 86 | |
| 87 Создает неинициализированный экземпляр объекта. | |
| 88 | |
| 89 =back | |
| 90 | |
| 91 =р1 Cavearts | |
| 92 | |
| 93 Нужно заметить, что директива C<use base> работает не совсем прозрачно, если в нашем примере | |
| 94 класс C<Composite> наследуется от C<Baz>, а затем C<Foo>, то наследование от | |
| 95 C<Foo> не произойдет поскольку он уже имеется в C<Baz>. Вот не задача:) | |
| 96 | |
| 185 =cut | 97 =cut |
| 186 | 98 |
| 187 1; | 99 1; |
