Commit | Line | Data |
26626902 |
1 | NAME |
2 | Class::C3 - A pragma to use the C3 method resolution order algortihm |
95bebf8c |
3 | |
26626902 |
4 | SYNOPSIS |
5 | package A; |
6 | use Class::C3; |
7 | sub hello { 'A::hello' } |
95bebf8c |
8 | |
26626902 |
9 | package B; |
10 | use base 'A'; |
11 | use Class::C3; |
95bebf8c |
12 | |
26626902 |
13 | package C; |
14 | use base 'A'; |
15 | use Class::C3; |
95bebf8c |
16 | |
26626902 |
17 | sub hello { 'C::hello' } |
95bebf8c |
18 | |
26626902 |
19 | package D; |
20 | use base ('B', 'C'); |
21 | use Class::C3; |
95bebf8c |
22 | |
26626902 |
23 | # Classic Diamond MI pattern |
24 | # <A> |
25 | # / \ |
26 | # <B> <C> |
27 | # \ / |
28 | # <D> |
95bebf8c |
29 | |
26626902 |
30 | package main; |
31 | |
32 | # initializez the C3 module |
33 | # (formerly called in INIT) |
34 | Class::C3::initialize(); |
0a4d4e25 |
35 | |
26626902 |
36 | print join ', ' => Class::C3::calculateMRO('Diamond_D') # prints D, B, C, A |
663e8dcc |
37 | |
26626902 |
38 | print D->hello() # prints 'C::hello' instead of the standard p5 'A::hello' |
39 | |
40 | D->can('hello')->(); # can() also works correctly |
41 | UNIVERSAL::can('D', 'hello'); # as does UNIVERSAL::can() |
95bebf8c |
42 | |
26626902 |
43 | DESCRIPTION |
44 | This is pragma to change Perl 5's standard method resolution order from |
45 | depth-first left-to-right (a.k.a - pre-order) to the more sophisticated |
46 | C3 method resolution order. |
95bebf8c |
47 | |
26626902 |
48 | What is C3? |
49 | C3 is the name of an algorithm which aims to provide a sane method |
50 | resolution order under multiple inheritence. It was first introduced in |
51 | the langauge Dylan (see links in the "SEE ALSO" section), and then later |
52 | adopted as the prefered MRO (Method Resolution Order) for the new-style |
53 | classes in Python 2.3. Most recently it has been adopted as the |
54 | 'canonical' MRO for Perl 6 classes, and the default MRO for Parrot |
55 | objects as well. |
95bebf8c |
56 | |
26626902 |
57 | How does C3 work. |
58 | C3 works by always preserving local precendence ordering. This |
59 | essentially means that no class will appear before any of it's |
60 | subclasses. Take the classic diamond inheritence pattern for instance: |
61 | |
62 | <A> |
63 | / \ |
64 | <B> <C> |
65 | \ / |
66 | <D> |
67 | |
68 | The standard Perl 5 MRO would be (D, B, A, C). The result being that A |
69 | appears before C, even though C is the subclass of A. The C3 MRO |
70 | algorithm however, produces the following MRO (D, B, C, A), which does |
71 | not have this same issue. |
72 | |
73 | This example is fairly trival, for more complex examples and a deeper |
74 | explaination, see the links in the "SEE ALSO" section. |
75 | |
76 | How does this module work? |
77 | This module uses a technique similar to Perl 5's method caching. When |
78 | "Class::C3::initialize" is called, this module calculates the MRO of all |
79 | the classes which called "use Class::C3". It then gathers information |
80 | from the symbol tables of each of those classes, and builds a set of |
81 | method aliases for the correct dispatch ordering. Once all these |
82 | C3-based method tables are created, it then adds the method aliases into |
83 | the local classes symbol table. |
84 | |
85 | The end result is actually classes with pre-cached method dispatch. |
86 | However, this caching does not do well if you start changing your @ISA |
87 | or messing with class symbol tables, so you should consider your classes |
88 | to be effectively closed. See the CAVEATS section for more details. |
89 | |
90 | OPTIONAL LOWERCASE PRAGMA |
91 | This release also includes an optional module c3 in the opt/ folder. I |
92 | did not include this in the regular install since lowercase module names |
93 | are considered *"bad"* by some people. However I think that code looks |
94 | much nicer like this: |
95 | |
96 | package MyClass; |
97 | use c3; |
98 | |
99 | The the more clunky: |
100 | |
101 | package MyClass; |
102 | use Class::C3; |
103 | |
104 | But hey, it's your choice, thats why it is optional. |
105 | |
106 | FUNCTIONS |
107 | calculateMRO ($class) |
108 | Given a $class this will return an array of class names in the |
109 | proper C3 method resolution order. |
110 | |
111 | initialize |
112 | This must be called to initalize the C3 method dispatch tables, this |
113 | module will not work if you do not do this. It is advised to do this |
114 | as soon as possible after loading any classes which use C3. Here is |
115 | a quick code example: |
116 | |
117 | package Foo; |
118 | use Class::C3; |
119 | # ... Foo methods here |
120 | |
121 | package Bar; |
122 | use Class::C3; |
123 | use base 'Foo'; |
124 | # ... Bar methods here |
125 | |
126 | package main; |
127 | |
128 | Class::C3::initialize(); # now it is safe to use Foo and Bar |
129 | |
130 | This function used to be called automatically for you in the INIT |
131 | phase of the perl compiler, but that lead to warnings if this module |
132 | was required at runtime. After discussion with my user base (the |
133 | DBIx::Class folks), we decided that calling this in INIT was more of |
134 | an annoyance than a convience. I apologize to anyone this causes |
135 | problems for (although i would very suprised if I had any other |
136 | users other than the DBIx::Class folks). The simplest solution of |
137 | course is to define your own INIT method which calls this function. |
138 | |
139 | NOTE: |
140 | |
141 | If "initialize" detects that "initialize" has already been executed, |
142 | it will "uninitialize" and clear the MRO cache first. |
143 | |
144 | uninitialize |
145 | Calling this function results in the removal of all cached methods, |
146 | and the restoration of the old Perl 5 style dispatch order |
147 | (depth-first, left-to-right). |
148 | |
149 | reinitialize |
150 | This is an alias for "initialize" above. |
151 | |
152 | METHOD REDISPATCHING |
153 | It is always useful to be able to re-dispatch your method call to the |
154 | "next most applicable method". This module provides a pseudo package |
155 | along the lines of "SUPER::" or "NEXT::" which will re-dispatch the |
156 | method along the C3 linearization. This is best show with an examples. |
157 | |
158 | # a classic diamond MI pattern ... |
159 | <A> |
160 | / \ |
161 | <B> <C> |
162 | \ / |
163 | <D> |
164 | |
165 | package A; |
166 | use c3; |
167 | sub foo { 'A::foo' } |
168 | |
169 | package B; |
170 | use base 'A'; |
171 | use c3; |
172 | sub foo { 'B::foo => ' . (shift)->next::method() } |
173 | |
174 | package B; |
175 | use base 'A'; |
176 | use c3; |
177 | sub foo { 'C::foo => ' . (shift)->next::method() } |
178 | |
179 | package D; |
180 | use base ('B', 'C'); |
181 | use c3; |
182 | sub foo { 'D::foo => ' . (shift)->next::method() } |
183 | |
184 | print D->foo; # prints out "D::foo => B::foo => C::foo => A::foo" |
185 | |
186 | A few things to note. First, we do not require you to add on the method |
187 | name to the "next::method" call (this is unlike "NEXT::" and "SUPER::" |
188 | which do require that). This helps to enforce the rule that you cannot |
189 | dispatch to a method of a different name (this is how "NEXT::" behaves |
190 | as well). |
191 | |
192 | The next thing to keep in mind is that you will need to pass all |
193 | arguments to "next::method" it can not automatically use the current @_. |
194 | |
195 | If "next::method" cannot find a next method to re-dispatch the call to, |
196 | it will throw an exception. You can use "next::can" to see if |
197 | "next::method" will succeed before you call it like so: |
198 | |
199 | $self->next::method(@_) if $self->next::can; |
200 | |
201 | Additionally, you can use "maybe::next::method" as a shortcut to only |
202 | call the next method if it exists. The previous example could be simply |
203 | written as: |
204 | |
205 | $self->maybe::next::method(@_); |
206 | |
207 | There are some caveats about using "next::method", see below for those. |
208 | |
209 | CAVEATS |
210 | This module used to be labeled as *experimental*, however it has now |
211 | been pretty heavily tested by the good folks over at DBIx::Class and I |
212 | am confident this module is perfectly usable for whatever your needs |
213 | might be. |
214 | |
215 | But there are still caveats, so here goes ... |
216 | |
217 | Use of "SUPER::". |
218 | The idea of "SUPER::" under multiple inheritence is ambigious, and |
219 | generally not recomended anyway. However, it's use in conjuntion |
220 | with this module is very much not recommended, and in fact very |
221 | discouraged. The recommended approach is to instead use the supplied |
222 | "next::method" feature, see more details on it's usage above. |
223 | |
224 | Changing @ISA. |
225 | It is the author's opinion that changing @ISA at runtime is pure |
226 | insanity anyway. However, people do it, so I must caveat. Any |
227 | changes to the @ISA will not be reflected in the MRO calculated by |
228 | this module, and therefor probably won't even show up. If you do |
229 | this, you will need to call "reinitialize" in order to recalulate |
230 | all method dispatch tables. See the "reinitialize" documentation and |
231 | an example in t/20_reinitialize.t for more information. |
232 | |
233 | Adding/deleting methods from class symbol tables. |
234 | This module calculates the MRO for each requested class by |
235 | interogatting the symbol tables of said classes. So any symbol table |
236 | manipulation which takes place after our INIT phase is run will not |
237 | be reflected in the calculated MRO. Just as with changing the @ISA, |
238 | you will need to call "reinitialize" for any changes you make to |
239 | take effect. |
240 | |
241 | Calling "next::method" from methods defined outside the class |
242 | There is an edge case when using "next::method" from within a |
243 | subroutine which was created in a different module than the one it |
244 | is called from. It sounds complicated, but it really isn't. Here is |
245 | an example which will not work correctly: |
246 | |
247 | *Foo::foo = sub { (shift)->next::method(@_) }; |
248 | |
249 | The problem exists because the anonymous subroutine being assigned |
250 | to the glob *Foo::foo will show up in the call stack as being called |
251 | "__ANON__" and not "foo" as you might expect. Since "next::method" |
252 | uses "caller" to find the name of the method it was called in, it |
253 | will fail in this case. |
254 | |
255 | But fear not, there is a simple solution. The module "Sub::Name" |
256 | will reach into the perl internals and assign a name to an anonymous |
257 | subroutine for you. Simply do this: |
258 | |
259 | use Sub::Name 'subname'; |
260 | *Foo::foo = subname 'Foo::foo' => sub { (shift)->next::method(@_) }; |
261 | |
262 | and things will Just Work. Of course this is not always possible to |
263 | do, but to be honest, I just can't manage to find a workaround for |
264 | it, so until someone gives me a working patch this will be a known |
265 | limitation of this module. |
266 | |
267 | COMPATIBILITY |
268 | If your software requires Perl 5.9.5 or higher, you do not need |
269 | Class::C3, you can simply "use mro 'c3'", and not worry about |
270 | "initialize()", avoid some of the above caveats, and get the best |
271 | possible performance. See mro for more details. |
272 | |
273 | If your software is meant to work on earlier Perls, use Class::C3 as |
274 | documented here. Class::C3 will detect Perl 5.9.5+ and take advantage of |
275 | the core support when available. |
276 | |
277 | Class::C3::XS |
278 | This module will load Class::C3::XS if it's installed and you are |
279 | running on a Perl version older than 5.9.5. Installing this is |
280 | recommended when possible, as it results in significant performance |
281 | improvements (but unlike the 5.9.5+ core support, it still has all of |
282 | the same caveats as Class::C3). |
283 | |
284 | CODE COVERAGE |
285 | Devel::Cover was reporting 94.4% overall test coverage earlier in this |
286 | module's life. Currently, the test suite does things that break under |
287 | coverage testing, but it is fair to assume the coverage is still close |
288 | to that value. |
289 | |
290 | SEE ALSO |
291 | The original Dylan paper |
292 | <http://www.webcom.com/haahr/dylan/linearization-oopsla96.html> |
293 | |
294 | The prototype Perl 6 Object Model uses C3 |
295 | <http://svn.openfoundry.org/pugs/perl5/Perl6-MetaModel/> |
296 | |
297 | Parrot now uses C3 |
298 | <http://aspn.activestate.com/ASPN/Mail/Message/perl6-internals/2746631> |
299 | <http://use.perl.org/~autrijus/journal/25768> |
300 | |
301 | Python 2.3 MRO related links |
302 | <http://www.python.org/2.3/mro.html> |
303 | <http://www.python.org/2.2.2/descrintro.html#mro> |
304 | |
305 | C3 for TinyCLOS |
306 | <http://www.call-with-current-continuation.org/eggs/c3.html> |
307 | |
308 | ACKNOWLEGEMENTS |
309 | Thanks to Matt S. Trout for using this module in his module DBIx::Class |
310 | and finding many bugs and providing fixes. |
311 | Thanks to Justin Guenther for making "next::method" more robust by |
312 | handling calls inside "eval" and anon-subs. |
313 | Thanks to Robert Norris for adding support for "next::can" and |
314 | "maybe::next::method". |
315 | |
316 | AUTHOR |
317 | Stevan Little, <stevan@iinteractive.com> |
318 | |
319 | Brandon L. Black, <blblack@gmail.com> |
320 | |
321 | COPYRIGHT AND LICENSE |
322 | Copyright 2005, 2006 by Infinity Interactive, Inc. |
323 | |
324 | <http://www.iinteractive.com> |
325 | |
326 | This library is free software; you can redistribute it and/or modify it |
327 | under the same terms as Perl itself. |
95bebf8c |
328 | |