Mercurial > pub > Impl
diff Lib/IMPL/declare.pm @ 197:6b1dda998839
Added IMPL::declare, IMPL::require, to simplify module definitions
IMPL::Transform now admires object inheritance while searching for the transformation
Added HTTP some exceptions
IMPL::Web::Application::RestResource almost implemented
author | sergey |
---|---|
date | Thu, 19 Apr 2012 02:10:02 +0400 |
parents | |
children | 2ffe6f661605 |
line wrap: on
line diff
--- /dev/null Thu Jan 01 00:00:00 1970 +0000 +++ b/Lib/IMPL/declare.pm Thu Apr 19 02:10:02 2012 +0400 @@ -0,0 +1,146 @@ +package IMPL::declare; +use strict; + +use Scalar::Util qw(set_prototype); + +sub import { + my ($self,$args) = @_; + + return unless $args; + + die "A hash reference is required" unless ref $args eq 'HASH'; + + no strict 'refs'; + + my $caller = caller; + + my $aliases = $args->{require} || {}; + + while( my ($alias, $class) = each %$aliases ) { + _require($class); + + *{"${caller}::$alias"} = set_prototype(sub { + $class + }, ''); + } + + my $base = $args->{base} || {}; + + my %ctor; + my @isa; + + if (ref $base eq 'ARRAY') { + @isa = map _require($_), @$base if @$base; + } elsif (ref $base eq 'HASH' ) { + while ( my ($class,$mapper) = each %$base ) { + $class = $aliases->{$class} || _require($class); + + push @isa,$class; + $ctor{$class} = $mapper; + } + } + + *{"${caller}::CTOR"} = \%ctor; + *{"${caller}::ISA"} = \@isa; +} + +sub _require { + my ($class) = @_; + + if (not $class =~ s/^-//) { + (my $file = $class) =~ s/::|'/\//g; + require "$file.pm"; + } + $class; +} + + +1; + +__END__ + +=pod + +=head1 NAME + +C<IMPL::declare> - описывает класс + +=head1 SYNOPSIS + +=begin code + +package My::Bar; + +use IMPL::declare { + require => { + TFoo => 'My::Foo', + TBox => 'My::Box' + }, + base => { + TFoo => '@_', + 'IMPL::Object' => undef, + } +} + +sub CreateBox { + my ($this) = @_; + return TBox->new($this); +} + +=end code + +Специальная ситрока C<@_> означает передачу параметров конструктора текущего класса конструктору +базового класса без изменений. + +=head1 DESCRIPTION + +Описывает текущий пакет(модуль) как класс. В качестве параметра получает ссылку на хеш, +в которой храняться метаданные для объявления класса. + +=head1 METADATA + +=head2 C<require> + +Содержит ссылку на хеш с синонимами модулей, которые будут доступны в текушем модуле, +аналогично использованию C<IMPL::require>. Однако, если модуль не требует загрузки при +помощи C<require> нужно использовать префикс C<'-'> в его имени + +=begin code + +{ + require => { + TObject => 'IMPL::Object', # will be loaded with require + TFoo => '-My:App::Data::Foo' # will not use 'require' to load module + } +} + +=end code + +=head2 C<base> + +Обисывает базове классы для текущего класса. Если данный параметр - ссылка массив, то +этот массив будет превращен в массив C<@ISA>. Если данный параметр - ссылка на хеш, то +его ключи опичавют список базовых классов, а значения - преобразование параметров для +вызова базовых конструкторов. + +В качестве имен базовых классов могут быть как полные имена модулей, так и назначенные +ранее псевдонимы. Использование префикса C<'-'> перед B<полным именем модуля> означает, +что модуль не требуется загружать, в случае с псевдонимами, префикс C<'-'> уже был указан +при их объявлении. + +=begin code + +{ + require => { + TFoo => '-My:App::Data::Foo' # will not use 'require' to load module + }, + base => { + TFoo => '@_', # pass parameters unchanged + 'My::Base::Class' => sub { name => $_[0], data => $_[1] }, # remap parameters + '-My::Extentions' => undef, # do not pass any parameters + } +} + +=end code + +=cut \ No newline at end of file