also handle undef inputs
[p5sagit/Safe-Isa.git] / lib / Safe / Isa.pm
CommitLineData
e6995dc6 1package Safe::Isa;
2
3use strict;
4use warnings FATAL => 'all';
5use Scalar::Util qw(blessed);
7b1885ee 6use Exporter 5.57 qw(import);
e6995dc6 7
762424c0 8our $VERSION = '1.000004';
e6995dc6 9
5e41c170 10our @EXPORT = qw($_call_if_object $_call_if_object_or_classname $_isa $_can $_does $_DOES);
e6995dc6 11
12our $_call_if_object = sub {
13 my ($obj, $method) = (shift, shift);
14 return unless blessed($obj);
15 return $obj->$method(@_);
16};
17
5e41c170 18our $_call_if_object_or_classname = sub {
19 my ($thing, $method) = (shift, shift);
0b257d22 20 return unless blessed($thing) or defined($thing) and do {
5e41c170 21 no strict 'refs';
22 %{"main::${thing}::"}
23 };
24 return $thing->$method(@_);
25};
26
e6995dc6 27our ($_isa, $_can, $_does, $_DOES) = map {
28 my $method = $_;
5e41c170 29 sub { my $obj = shift; $obj->$_call_if_object_or_classname($method => @_) }
e6995dc6 30} qw(isa can does DOES);
31
32=head1 NAME
33
5e41c170 34Safe::Isa - Call isa, can, does and DOES safely on arbitrary things
e6995dc6 35
36=head1 SYNOPSIS
37
38 use strict;
39 use warnings;
40
41 { package Foo; sub new { bless({}, $_[0]) } }
42 { package Bar; our @ISA = qw(Foo); sub bar { 1 } }
43
44 my $foo = Foo->new;
45 my $bar = Bar->new;
5e41c170 46 my $class = 'Bar';
e6995dc6 47 my $blam = [ 42 ];
48
49 # basic isa usage -
50
51 $foo->isa('Foo'); # true
52 $bar->isa('Foo'); # true
5e41c170 53 $class->isa('Foo') # true
e6995dc6 54 $blam->isa('Foo'); # BOOM
55
56 $foo->can('bar'); # false
57 $bar->can('bar'); # true
5e41c170 58 $class->can('bar); # true
e6995dc6 59 $blam->can('bar'); # BOOM
60
61 # Safe::Isa usage -
62
63 use Safe::Isa;
64
65 $foo->$_isa('Foo'); # true
66 $bar->$_isa('Foo'); # true
5e41c170 67 $class->isa('Foo') # true
e6995dc6 68 $blam->$_isa('Foo'); # false, no boom today
69
70 $foo->$_can('bar'); # false
71 $bar->$_can('bar'); # true
5e41c170 72 $class->can('bar); # true
e6995dc6 73 $blam->$_can('bar'); # false, no boom today
74
75Similarly:
76
77 $maybe_an_object->$_does('RoleName'); # true or false, no boom today
78 $maybe_an_object->$_DOES('RoleName'); # true or false, no boom today
79
80And just in case we missed a method:
81
82 $maybe_an_object->$_call_if_object(name => @args);
83
5e41c170 84or this might be closer to what you want:
85
86 $maybe_a_referent->$_call_if_object_or_class(name => @args);
87
e6995dc6 88Or to re-use a previous example for purposes of explication:
89
ff9518c5 90 $foo->$_call_if_object(isa => 'Foo'); # true
91 $bar->$_call_if_object(isa => 'Foo'); # true
92 $blam->$_call_if_object(isa => 'Foo'); # false, no boom today
e6995dc6 93
94=head1 DESCRIPTION
95
96How many times have you found yourself writing:
97
98 if ($obj->isa('Something')) {
99
100and then shortly afterwards cursing and changing it to:
101
102 if (Scalar::Util::blessed($obj) and $obj->isa('Something')) {
103
104Right. That's why this module exists.
105
106Since perl allows us to provide a subroutine reference or a method name to
107the -> operator when used as a method call, and a subroutine doesn't require
108the invocant to actually be an object, we can create safe versions of isa,
109can and friends by using a subroutine reference that only tries to call the
110method if it's used on an object. So:
111
112 my $isa_Foo = $maybe_an_object->$_call_if_object(isa => 'Foo');
113
114is equivalent to
115
116 my $isa_Foo = do {
117 if (Scalar::Util::blessed($maybe_an_object)) {
118 $maybe_an_object->isa('Foo');
119 } else {
120 undef;
121 }
122 };
123
fca38ff4 124Note that we don't handle trying class names, because many things are valid
125class names that you might not want to treat as one (like say "Matt") - the
126C<is_module_name> function from L<Module::Runtime> is a good way to check for
f94f3bbb 127something you might be able to call methods on if you want to do that.
fca38ff4 128
e6995dc6 129=head1 EXPORTS
130
131=head2 $_isa
132
133 $maybe_an_object->$_isa('Foo');
134
135If called on an object, calls C<isa> on it and returns the result, otherwise
136returns nothing.
137
138=head2 $_can
139
140 $maybe_an_object->$_can('Foo');
141
142If called on an object, calls C<can> on it and returns the result, otherwise
143returns nothing.
144
145=head2 $_does
146
147 $maybe_an_object->$_does('Foo');
148
149If called on an object, calls C<does> on it and returns the result, otherwise
150returns nothing.
151
152=head2 $_DOES
153
154 $maybe_an_object->$_DOES('Foo');
155
156If called on an object, calls C<DOES> on it and returns the result, otherwise
157returns nothing.
158
4703f64c 159=head2 $_call_if_object
e6995dc6 160
4703f64c 161 $maybe_an_object->$_call_if_object(method_name => @args);
e6995dc6 162
163If called on an object, calls C<method_name> on it and returns the result,
164otherwise returns nothing.
165
166=head1 AUTHOR
167
168mst - Matt S. Trout (cpan:MSTROUT) <mst@shadowcat.co.uk>
169
170=head1 CONTRIBUTORS
171
172None yet. Well volunteered? :)
173
174=head1 COPYRIGHT
175
176Copyright (c) 2012 the Safe::Isa L</AUTHOR> and L</CONTRIBUTORS>
177as listed above.
178
179=head1 LICENSE
180
181This library is free software and may be distributed under the same terms
182as perl itself.
183
184=cut