Mercurial > pub > Impl
comparison 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 |
comparison
equal
deleted
inserted
replaced
196:a705e848dcc7 | 197:6b1dda998839 |
---|---|
1 package IMPL::declare; | |
2 use strict; | |
3 | |
4 use Scalar::Util qw(set_prototype); | |
5 | |
6 sub import { | |
7 my ($self,$args) = @_; | |
8 | |
9 return unless $args; | |
10 | |
11 die "A hash reference is required" unless ref $args eq 'HASH'; | |
12 | |
13 no strict 'refs'; | |
14 | |
15 my $caller = caller; | |
16 | |
17 my $aliases = $args->{require} || {}; | |
18 | |
19 while( my ($alias, $class) = each %$aliases ) { | |
20 _require($class); | |
21 | |
22 *{"${caller}::$alias"} = set_prototype(sub { | |
23 $class | |
24 }, ''); | |
25 } | |
26 | |
27 my $base = $args->{base} || {}; | |
28 | |
29 my %ctor; | |
30 my @isa; | |
31 | |
32 if (ref $base eq 'ARRAY') { | |
33 @isa = map _require($_), @$base if @$base; | |
34 } elsif (ref $base eq 'HASH' ) { | |
35 while ( my ($class,$mapper) = each %$base ) { | |
36 $class = $aliases->{$class} || _require($class); | |
37 | |
38 push @isa,$class; | |
39 $ctor{$class} = $mapper; | |
40 } | |
41 } | |
42 | |
43 *{"${caller}::CTOR"} = \%ctor; | |
44 *{"${caller}::ISA"} = \@isa; | |
45 } | |
46 | |
47 sub _require { | |
48 my ($class) = @_; | |
49 | |
50 if (not $class =~ s/^-//) { | |
51 (my $file = $class) =~ s/::|'/\//g; | |
52 require "$file.pm"; | |
53 } | |
54 $class; | |
55 } | |
56 | |
57 | |
58 1; | |
59 | |
60 __END__ | |
61 | |
62 =pod | |
63 | |
64 =head1 NAME | |
65 | |
66 C<IMPL::declare> - описывает класс | |
67 | |
68 =head1 SYNOPSIS | |
69 | |
70 =begin code | |
71 | |
72 package My::Bar; | |
73 | |
74 use IMPL::declare { | |
75 require => { | |
76 TFoo => 'My::Foo', | |
77 TBox => 'My::Box' | |
78 }, | |
79 base => { | |
80 TFoo => '@_', | |
81 'IMPL::Object' => undef, | |
82 } | |
83 } | |
84 | |
85 sub CreateBox { | |
86 my ($this) = @_; | |
87 return TBox->new($this); | |
88 } | |
89 | |
90 =end code | |
91 | |
92 Специальная ситрока C<@_> означает передачу параметров конструктора текущего класса конструктору | |
93 базового класса без изменений. | |
94 | |
95 =head1 DESCRIPTION | |
96 | |
97 Описывает текущий пакет(модуль) как класс. В качестве параметра получает ссылку на хеш, | |
98 в которой храняться метаданные для объявления класса. | |
99 | |
100 =head1 METADATA | |
101 | |
102 =head2 C<require> | |
103 | |
104 Содержит ссылку на хеш с синонимами модулей, которые будут доступны в текушем модуле, | |
105 аналогично использованию C<IMPL::require>. Однако, если модуль не требует загрузки при | |
106 помощи C<require> нужно использовать префикс C<'-'> в его имени | |
107 | |
108 =begin code | |
109 | |
110 { | |
111 require => { | |
112 TObject => 'IMPL::Object', # will be loaded with require | |
113 TFoo => '-My:App::Data::Foo' # will not use 'require' to load module | |
114 } | |
115 } | |
116 | |
117 =end code | |
118 | |
119 =head2 C<base> | |
120 | |
121 Обисывает базове классы для текущего класса. Если данный параметр - ссылка массив, то | |
122 этот массив будет превращен в массив C<@ISA>. Если данный параметр - ссылка на хеш, то | |
123 его ключи опичавют список базовых классов, а значения - преобразование параметров для | |
124 вызова базовых конструкторов. | |
125 | |
126 В качестве имен базовых классов могут быть как полные имена модулей, так и назначенные | |
127 ранее псевдонимы. Использование префикса C<'-'> перед B<полным именем модуля> означает, | |
128 что модуль не требуется загружать, в случае с псевдонимами, префикс C<'-'> уже был указан | |
129 при их объявлении. | |
130 | |
131 =begin code | |
132 | |
133 { | |
134 require => { | |
135 TFoo => '-My:App::Data::Foo' # will not use 'require' to load module | |
136 }, | |
137 base => { | |
138 TFoo => '@_', # pass parameters unchanged | |
139 'My::Base::Class' => sub { name => $_[0], data => $_[1] }, # remap parameters | |
140 '-My::Extentions' => undef, # do not pass any parameters | |
141 } | |
142 } | |
143 | |
144 =end code | |
145 | |
146 =cut |