File Coverage

blib/lib/mixin/with.pm
Criterion Covered Total %
statement 22 22 100.0
branch n/a
condition n/a
subroutine 6 6 100.0
pod n/a
total 28 28 100.0


line stmt bran cond sub pod time code
1             package mixin::with;
2              
3 8     8   798761 use strict;
  8         16  
  8         321  
4 8     8   43 use warnings;
  8         30  
  8         492  
5 8     8   48 no strict 'refs';
  8         17  
  8         365  
6 8     8   49 use vars qw($VERSION);
  8         35  
  8         2676  
7             $VERSION = '0.09';
8              
9             =head1 NAME
10              
11             mixin::with - declaring a mix-in class
12              
13             =head1 SYNOPSIS
14              
15             package Dog::Retriever;
16             use mixin::with 'Dog';
17              
18              
19             =head1 DESCRIPTION
20              
21             mixin::with is used to declare mix-in classes.
22              
23              
24             =head2 When to use a mixin?
25              
26             Mixin classes useful for those that I to an
27             existing class. If you find yourself doing:
28              
29             package Foo::ExtraStuff;
30             use base 'Foo';
31             sub new_method { ... }
32              
33             package Bar;
34             use base qw(Foo Foo::ExtraStuff);
35              
36             it's a good indication that Foo::ExtraStuff might do better as a mixin.
37              
38             Instead of mixins, please consider using traits. See L for an implementaiton.
39              
40              
41             =head2 How?
42              
43             Basic usage is simple:
44              
45             package Foo::Extra;
46             use mixin::with 'Foo';
47              
48             sub new_thing {
49             my($self) = shift;
50             ...normal method...
51             }
52              
53             C is I to subclassing from 'Foo'.
54              
55             All public methods of Foo::Extra will be mixed in. mixin::with
56             considers all methods that don't start with an '_' as public.
57              
58              
59             =head2 Limitations of mixins
60              
61             There's one critical difference between a normal subclass and one
62             intended to be mixin. It can have no private methods. Instead, use lexical methods.
63              
64             my $private = sub { ... };
65             $self->$private(@args);
66              
67             instead of
68              
69             sub _private { ... }
70             $self->_private(@args);
71              
72             Don't worry, it's the same thing.
73              
74              
75             =cut
76              
77             my %Mixers = ();
78             my $Tmp_Counter = 0;
79             sub import {
80 9     9   103 my($class, $mixed_with) = @_;
81 9         27 my $mixin = caller;
82              
83 9         29 my $tmp_pkg = __PACKAGE__.'::tmp'.$Tmp_Counter++;
84 9         39 $Mixers{$mixin} = { mixed_with => $mixed_with,
85             tmp_pkg => $tmp_pkg,
86             };
87              
88 9         64 require base;
89              
90 9         812 eval sprintf q{
91             package %s;
92             base->import($mixed_with);
93             }, $mixin;
94              
95 9         2407 return 1;
96             }
97              
98              
99             sub __mixers {
100 10     10   25 my($class, $mixin) = @_;
101              
102 10         17 return @{$Mixers{$mixin}}{'mixed_with', 'tmp_pkg'};
  10         50  
103             }
104              
105              
106             =head1 FAQ
107              
108             =over 4
109              
110             =item What if I want to mixin with anything?
111              
112             Sometimes a mixin does not care what it mixes in with. Consider a
113             logging or error handling mixin. For these, simply mixin with
114             UNIVERSAL.
115              
116             package My::Errors;
117             use mixin::with qw(UNIVERSAL);
118              
119              
120             =item Why do I have to declare what I mixin with?
121              
122             Two reasons. One is technical, it allows C to work.
123              
124             The other is organizational. It is rare that a mixin is intended to be mixed with any old class. It often uses methods as if it were a subclass. For this reason it is good that it declares this relationship explicitly else the mixee won't be aware of the mixin's expectations.
125              
126              
127             =item Why use mixins instead of traits?
128              
129             Good question. Traits are definately a better idea then mixins, but mixins have two advantages. They're simpler to explain, acting like a gateway drug to traits by introducing the concept of OO reuse by class composition rather than inheritance.
130              
131             The other is mixins work more like a drop-in replacement for multiple inheritance. In a large, hairy hierarchy mixins can often be used to trim the inheritance bush and make sense of things with a minimum of modification to the code. Once this basic repair is done, the work of converting to traits can begin.
132              
133             If these advantages don't apply, proceed directly to traits.
134              
135             =back
136              
137             =head1 AUTHOR
138              
139             Current ( ~ 2024 ) maintainer: Shlomi Fish ( L ).
140              
141             Original author/maintainer:
142              
143             Michael G Schwern
144              
145             =head1 LICENSE
146              
147             Copyright 2002-2010 by Michael G Schwern
148              
149             This library is free software; you can redistribute it and/or modify it
150             under the same terms as Perl itself.
151              
152             L
153              
154             Shlomi Fish disclaims all copyright ownership to his changes.
155              
156             =head1 SEE ALSO
157              
158             L, L from which I stole this idea.
159              
160             =cut
161              
162             1;
163