File: Mixin.pm

package info (click to toggle)
libbadger-perl 0.16-3
  • links: PTS, VCS
  • area: main
  • in suites: forky, sid, trixie
  • size: 2,400 kB
  • sloc: perl: 11,004; makefile: 9
file content (182 lines) | stat: -rw-r--r-- 4,891 bytes parent folder | download
1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
28
29
30
31
32
33
34
35
36
37
38
39
40
41
42
43
44
45
46
47
48
49
50
51
52
53
54
55
56
57
58
59
60
61
62
63
64
65
66
67
68
69
70
71
72
73
74
75
76
77
78
79
80
81
82
83
84
85
86
87
88
89
90
91
92
93
94
95
96
97
98
99
100
101
102
103
104
105
106
107
108
109
110
111
112
113
114
115
116
117
118
119
120
121
122
123
124
125
126
127
128
129
130
131
132
133
134
135
136
137
138
139
140
141
142
143
144
145
146
147
148
149
150
151
152
153
154
155
156
157
158
159
160
161
162
163
164
165
166
167
168
169
170
171
172
173
174
175
176
177
178
179
180
181
182
#========================================================================
#
# Badger::Mixin
#
# DESCRIPTION
#   Base class for mixins that allow you to "mix in" functionality using
#   composition rather than inheritance.  Similar in concept to roles,
#   although operating at a slightly lower level.
#
# AUTHOR
#   Andy Wardley   <abw@wardley.org>
#
#========================================================================

package Badger::Mixin;

use Badger::Class
    version   => 3.00,
    debug     => 0,
    base      => 'Badger::Exporter',
    import    => 'class',
    constants => 'PKG REFS ONCE ARRAY DELIMITER',
    words     => 'EXPORT_TAGS MIXINS';


sub mixin {
    my $self   = shift;
    my $target = shift || (caller())[0];
    my $class  = $self->class;
    my $mixins = $class->list_vars(MIXINS); 
    $self->debug("mixinto($target): ", $self->dump_data($mixins), "\n") if $DEBUG;
    $self->export($target, $mixins);
}

sub mixins {
    my $self   = shift;
    my $syms   = @_ == 1 ? shift : [ @_ ];
    my $class  = $self->class;
    my $mixins = $class->var_default(MIXINS, [ ]);
    
    $syms = [ split(DELIMITER, $syms) ] 
        unless ref $syms eq ARRAY;

    push(@$mixins, @$syms);
    $self->export_any($syms);
    
    return $mixins;
}


1;

=head1 NAME

Badger::Mixin - base class mixin object

=head1 SYNOPSIS

The C<Badger::Mixin> module is a base class for mixin modules.  
You can use the L<Badger::Class> module to declare mixins:

    package Your::Mixin::Module;
    
    use Badger::Class
        mixins => '$FOO @BAR %BAZ bam';
        
    # some sample data/methods to mixin
    our $FOO = 'Some random text';
    our @BAR = qw( foo bar baz );
    our %BAZ = ( hello => 'world' );
    sub bam { 'just testing' };

Behind the scenes this adds C<Badger::Mixin> as a base class of 
C<Your::Mixin::Module> and calls the L<mixins> method to declare
what symbols can be mixed into another module.  You can write this
code manually if you prefer:

    package Your::Mixin::Module;
    
    use base 'Badger::Mixin';
    
    __PACKAGE__->mixins('$FOO @BAR %BAZ bam');
    
    # sample data/methods as before

=head1 DESCRIPTION

The L<Badger::Mixin> module is a base class for mixin modules. Mixins are
modules that implement functionality that can be mixed into other modules.
This allows you to create modules using composition instead of misuing
inheritance.

The easiest way to define a mixin module is via the C<Badger::Class> module.

    package Your::Mixin::Module;
    
    use Badger::Class
        mixins => '$FOO @BAR %BAZ bam';

This is syntactic sugar for the following code:

    package Your::Mixin::Module;
    
    use base 'Badger::Mixin';
    __PACKAGE__->mixins('$FOO @BAR %BAZ bam');

The mixin module declares what symbols it makes available for mixing using the
L<mixins()> (plural) method (either indirectly as in the first example,
or directly as in the second).

The L<mixin()> (singular) method can then be used to mix those symbols into
another module. L<Badger::Class> provides the L<mixin|Badger::Class/mixin>
hook which you can use:

    package Your::Other::Module;
    
    use Badger::Class
        mixin => 'Your::Mixin::Module';

Or you can call the L<mixin()> method manually if you prefer.

    package Your::Other::Module;
    
    use Your::Mixin::Module;
    Your::Mixin::Module->mixin(__PACKAGE__);

Mixins are little more than modules with a specialised export mechanism. In
fact, the C<Badger::Mixin> module uses the L<Badger::Exporter> behind the
scenes to export the mixin symbols into the target package. Mixins are
intentionally simple. If you want to do anything more complicated in terms of
exporting symbols then you should use the L<Badger::Exporter> module directly
instead.

=head1 METHODS

=head2 mixins($symbols)

This method is used to declare what symbols are available for mixing in to
other packages. Symbols can be specified as a list of items, a reference to a
list of items or as a single whitespace delimited string.

    package Your::Module;
    use base 'Badger::Mixin';
    
    # either list of symbols...
    __PACKAGE__->mixins('$FOO', '@BAR', '%BAZ', 'bam');
    
    # ...or reference to a list
    __PACKAGE__->mixins(['$FOO', '@BAR', '%BAZ', 'bam']);
    
    # ...or single string of whitespace delimited symbols
    __PACKAGE__->mixins('$FOO @BAR %BAZ bam');

=head2 mixin($package)

This method is used to mixin the symbols declared via L<mixins()> into 
the package specified by the C<$package> argument.

    Your::Mixin::Module->mixin('My::Module');

=head1 AUTHOR

Andy Wardley L<http://wardley.org/>

=head1 COPYRIGHT

Copyright (C) 2005-2009 Andy Wardley. All rights reserved.

=head1 SEE ALSO

L<Badger::Class>

=cut

# Local Variables:
# mode: Perl
# perl-indent-level: 4
# indent-tabs-mode: nil
# End:
#
# vim: expandtab shiftwidth=4:
# TextMate: rocks my world