Mercurial > pub > Impl
diff lib/IMPL/Object/Abstract.pm @ 407:c6e90e02dd17 ref20150831
renamed Lib->lib
author | cin |
---|---|
date | Fri, 04 Sep 2015 19:40:23 +0300 |
parents | |
children | ee36115f6a34 |
line wrap: on
line diff
--- /dev/null Thu Jan 01 00:00:00 1970 +0000 +++ b/lib/IMPL/Object/Abstract.pm Fri Sep 04 19:40:23 2015 +0300 @@ -0,0 +1,189 @@ +package IMPL::Object::Abstract; +use strict; +use warnings; + +use parent qw(IMPL::Class::Meta); +use Carp qw(croak); + +our $MemoryLeakProtection; +my $Cleanup = 0; + +my %cacheCTOR; + +my $t = 0; +sub cache_ctor { + my $class = shift; + + no strict 'refs'; + my @sequence; + + my $refCTORS = *{"${class}::CTOR"}{HASH}; + + foreach my $super ( @{"${class}::ISA"} ) { + my $superSequence = $cacheCTOR{$super} || cache_ctor($super); + + my $mapper = $refCTORS ? $refCTORS->{$super} : undef; + if (ref $mapper eq 'CODE') { + if ($mapper == *_pass_through_mapper{CODE}) { + push @sequence,@$superSequence; + } else { + push @sequence, sub { + my $this = shift; + $this->$_($mapper->(@_)) foreach @$superSequence; + } if @$superSequence; + } + } elsif ($mapper and not ref $mapper and $mapper eq '@_') { + push @sequence,@$superSequence; + } else { + warn "Unsupported mapper type, in '$class' for the super class '$super'" if $mapper; + push @sequence, sub { + my $this = shift; + $this->$_() foreach @$superSequence; + } if @$superSequence; + } + } + + push @sequence, *{"${class}::CTOR"}{CODE} if *{"${class}::CTOR"}{CODE}; + + $cacheCTOR{$class} = \@sequence; + return \@sequence; +} + +sub dump_ctor { + my ($self) = @_; + $self = ref $self || $self; + + warn "dumping $self .ctor"; + warn "$_" foreach @{$cacheCTOR{$self}||[]}; +} + +sub callCTOR { + my $self = shift; + my $class = ref $self; + + $self->$_(@_) foreach @{$cacheCTOR{$class} || cache_ctor($class)}; +} + +sub _init_dtor { + my ($class) = @_; + + no strict 'refs'; + + # avoid warnings for classes without destructors + no warnings 'once'; + + my @dtors; + + my @hierarchy = ($class); + my %visited; + + while(my $subclass = shift @hierarchy) { + if(*{"${subclass}::DTOR"}{CODE}) { + push @dtors, *{"${subclass}::DTOR"}{CODE}; + } + + push @hierarchy, @{"${subclass}::ISA"}; + } + + if (@dtors) { + + return *{"${class}::callDTOR"} = sub { + my ($self) = @_; + my $selfClass = ref $self; + if ($selfClass ne $class) { + goto &{$selfClass->_init_dtor()}; + } else { + map $_->($self), @dtors; + } + } + + } else { + return *{"${class}::callDTOR"} = sub { + my $self = ref $_[0]; + + goto &{$self->_init_dtor()} unless $self eq $class; + } + } +} + +__PACKAGE__->_init_dtor(); + +sub toString { + my $self = shift; + + return (ref $self || $self); +} + +sub _typeof { + ref $_[0] || $_[0]; +} + +sub isDisposed { + 0; +} + +sub DESTROY { + shift->callDTOR(); +} + +sub END { + $Cleanup = 1; +} + +sub _pass_through_mapper { + @_; +} + +sub PassArgs { + \&_pass_through_mapper; +} + +sub PassThroughArgs { + my $class = shift; + $class = ref $class || $class; + no strict 'refs'; + no warnings 'once'; + ${"${class}::CTOR"}{$_} = \&_pass_through_mapper foreach @{"${class}::ISA"}; +} + +package self; + +our $AUTOLOAD; +sub AUTOLOAD { + goto &{caller(). substr $AUTOLOAD,4}; +} + +package supercall; + +our $AUTOLOAD; +sub AUTOLOAD { + my $sub; + my $methodName = substr $AUTOLOAD,9; + no strict 'refs'; + $sub = $_->can($methodName) and $sub->(@_) foreach @{caller().'::ISA'}; +} + +1; + +__END__ + +=pod +=head1 SYNOPSIS + +package MyBaseObject; +use parent qw(IMPL::Object::Abstract); + +sub new { + # own implementation of the new opeator +} + +sub surrogate { + # own implementation of the surrogate operator +} + +=head1 DESCRIPTION + +Реализация механизма вызова конструкторов и других вспомогательных вещей, кроме операторов +создания экземпляров. + +=cut