Mercurial > pub > Impl
comparison lib/IMPL/template.pm @ 407:c6e90e02dd17 ref20150831
renamed Lib->lib
author | cin |
---|---|
date | Fri, 04 Sep 2015 19:40:23 +0300 |
parents | |
children |
comparison
equal
deleted
inserted
replaced
406:f23fcb19d3c1 | 407:c6e90e02dd17 |
---|---|
1 package IMPL::template; | |
2 use strict; | |
3 use warnings; | |
4 | |
5 use IMPL::Class::Template(); | |
6 | |
7 sub import { | |
8 shift; | |
9 my %args = @_; | |
10 | |
11 my $class = caller; | |
12 | |
13 my @paramNames = grep m/\w+/, @{$args{parameters} || []}; | |
14 my $declare = $args{declare}; | |
15 my @isa = (@{$args{base} || []}, $class); | |
16 my %instances; | |
17 | |
18 no strict 'refs'; | |
19 | |
20 push @{"${class}::ISA"}, 'IMPL::Class::Template'; | |
21 | |
22 *{"${class}::$_"} = sub { die IMPL::InvalidOperationException("A template parameter isn't available here") } | |
23 foreach @paramNames; | |
24 | |
25 *{"${class}::spec"} = sub { | |
26 my ($self,@params) = @_; | |
27 | |
28 my $specClass = $self->makeName(@params); | |
29 | |
30 return $specClass if $instances{$specClass}; | |
31 | |
32 $instances{$specClass} = 1; | |
33 | |
34 for (my $i=0; $i < @paramNames; $i++) { | |
35 my $param = $params[$i]; | |
36 *{"${specClass}::$paramNames[$i]"} = sub { $param }; | |
37 } | |
38 | |
39 @{"${specClass}::ISA"} = @isa; | |
40 | |
41 &$declare($specClass) if $declare; | |
42 return $specClass; | |
43 }; | |
44 } | |
45 | |
46 1; | |
47 | |
48 __END__ | |
49 | |
50 =pod | |
51 | |
52 =head1 NAME | |
53 | |
54 C<IMPL::template> директива для объявления шаблона. | |
55 | |
56 =head1 SYNPOSIS | |
57 | |
58 =begin code | |
59 | |
60 package KeyValuePair; | |
61 | |
62 use IMPL::Class::Property; | |
63 | |
64 use IMPL::template ( | |
65 parameters => [qw(TKey TValue))], | |
66 base => [qw(IMPL::Object IMPL::Object::Autofill)], | |
67 declare => sub { | |
68 my ($class) = @_; | |
69 public $class->CreateProperty(key => prop_get | owner_set, { type => $class->TKey } ); | |
70 public $class->CreateProperty(value => prop_all, { type => $class->TValue} ); | |
71 | |
72 $class->PassThroughArgs; | |
73 } | |
74 ); | |
75 | |
76 BEGIN { | |
77 public property id => prop_get | owner_set, { type => 'integer'}; | |
78 } | |
79 | |
80 __PACKAGE__->PassThroughArgs; | |
81 | |
82 package MyCollection; | |
83 | |
84 use IMPL::Class::Property; | |
85 | |
86 use IMPL::lang; | |
87 use IMPL::template( | |
88 parameters => [qw(TKey TValue)], | |
89 base => [qw(IMPL::Object)], | |
90 declare => sub { | |
91 my ($class) = @_; | |
92 my $item_t = spec KeyValuePair($class->TKey,$class->TValue); | |
93 | |
94 public $class->CreateProperty(items => prop_get | prop_list, { type => $item_t } ); | |
95 | |
96 $class->static_accessor( ItemType => $item_t ); | |
97 } | |
98 ) | |
99 | |
100 sub Add { | |
101 my ($this,$key,$value) = @_; | |
102 | |
103 die new IMPL::ArgumentException( key => "Invalid argument type" ) unless is $key, $this->TKey; | |
104 die new IMPL::ArgumentException( value => "Invalid argument type" ) unless is $value, $this->TValue; | |
105 | |
106 $this->items->AddLast( $this->ItemType->new( key => $key, value => $value ) ); | |
107 } | |
108 | |
109 package main; | |
110 | |
111 use IMPL::require { | |
112 TFoo => 'Some::Package::Foo', | |
113 TBar => 'Some::Package::Bar' | |
114 }; | |
115 | |
116 my $TCol = spec MyCollection(TFoo, TBar); | |
117 | |
118 =end code | |
119 | |
120 =head1 DESCRIPTION | |
121 | |
122 Шаблоны используются для динамической генерации классов. Процесс создания класса | |
123 по шаблону называется специализацией, при этом создается новый класс: | |
124 | |
125 =over | |
126 | |
127 =item 1 | |
128 | |
129 Обявляется новый пакет с именем, вычисленным из имени и параметров шаблона | |
130 | |
131 =item 2 | |
132 | |
133 Формируется массив C<@ISA> для созаднного класса, в который добавляется имя шаблона | |
134 | |
135 =item 3 | |
136 | |
137 Формируются методы с именами параметров шаблона, возвращающие реальные значения параметров | |
138 | |
139 =item 4 | |
140 | |
141 Вызывается метод для конструирования специализиции | |
142 | |
143 =back | |
144 | |
145 =head1 MEMBERS | |
146 | |
147 =over | |
148 | |
149 =item C<spec(@params)> | |
150 | |
151 Метод, создающий специализацию шаблона. Может быть вызван как оператор. | |
152 | |
153 =back | |
154 | |
155 =cut |