summaryrefslogtreecommitdiff
path: root/lib
diff options
context:
space:
mode:
authorAbigail <abigail@abigail.be>2010-02-21 17:28:39 +0100
committerAbigail <abigail@abigail.be>2010-02-21 17:28:39 +0100
commit5b1f92675e6dc88f9cbebe99d6b5ca92f6275b33 (patch)
tree00f301d93760dc5e1d665449584797e22a0eaddd /lib
parent1225b9be59a602d01605c28a28b567a93e8c7df6 (diff)
parent3f89fda63a570ce262c8007047c0dc2a0d130779 (diff)
downloadperl-5b1f92675e6dc88f9cbebe99d6b5ca92f6275b33.tar.gz
Merge branch 'tie-scalar' into blead
Diffstat (limited to 'lib')
-rw-r--r--lib/Tie/Scalar.pm31
-rw-r--r--lib/Tie/Scalar.t36
2 files changed, 62 insertions, 5 deletions
diff --git a/lib/Tie/Scalar.pm b/lib/Tie/Scalar.pm
index 9bf03f9105..24e4ae79c3 100644
--- a/lib/Tie/Scalar.pm
+++ b/lib/Tie/Scalar.pm
@@ -1,6 +1,6 @@
package Tie::Scalar;
-our $VERSION = '1.01';
+our $VERSION = '1.02';
=head1 NAME
@@ -73,6 +73,18 @@ destruction of an instance.
=back
+=head2 Tie::Scalar vs Tie::StdScalar
+
+C<< Tie::Scalar >> provides all the necessary methods, but one should realize
+they do not do anything useful. Calling C<< Tie::Scalar::FETCH >> or
+C<< Tie::Scalar::STORE >> results in a (trappable) croak. And if you inherit
+from C<< Tie::Scalar >>, you I<must> provide either a C<< new >> or a
+C<< TIESCALAR >> method.
+
+If you are looking for a class that does everything for you you don't
+define yourself, use the C<< Tie::StdScalar >> class, not the
+C<< Tie::Scalar >> one.
+
=head1 MORE INFORMATION
The L<perltie> section uses a good example of tying scalars by associating
@@ -92,9 +104,20 @@ sub new {
sub TIESCALAR {
my $pkg = shift;
- if ($pkg->can('new') and $pkg ne __PACKAGE__) {
- warnings::warnif("WARNING: calling ${pkg}->new since ${pkg}->TIESCALAR is missing");
- $pkg->new(@_);
+ my $pkg_new = $pkg -> can ('new');
+
+ if ($pkg_new and $pkg ne __PACKAGE__) {
+ my $my_new = __PACKAGE__ -> can ('new');
+ if ($pkg_new == $my_new) {
+ #
+ # Prevent recursion
+ #
+ croak "$pkg must define either a TIESCALAR() or a new() method";
+ }
+
+ warnings::warnif ("WARNING: calling ${pkg}->new since " .
+ "${pkg}->TIESCALAR is missing");
+ $pkg -> new (@_);
}
else {
croak "$pkg doesn't define a TIESCALAR method";
diff --git a/lib/Tie/Scalar.t b/lib/Tie/Scalar.t
index 3c5d9b6146..fb33ca13cb 100644
--- a/lib/Tie/Scalar.t
+++ b/lib/Tie/Scalar.t
@@ -17,7 +17,7 @@ sub new { 'Fooled you.' }
package main;
use vars qw( $flag );
-use Test::More tests => 13;
+use Test::More tests => 16;
use_ok( 'Tie::Scalar' );
@@ -74,3 +74,37 @@ sub new {
sub DESTROY {
$main::flag = 1;
}
+
+
+#
+# Bug #72878: don't recurse forever if both new and TIESCALAR are missing.
+#
+package main;
+
+@NoMethods::ISA = qw [Tie::Scalar];
+
+eval {tie my $foo => "NoMethods"};
+
+like $@ =>
+ qr /\QNoMethods must define either a TIESCALAR() or a new() method/,
+ "croaks if both new() and TIESCALAR() are missing";
+
+#
+# Don't croak on missing new/TIESCALAR if you're inheriting one.
+#
+my $called1 = 0;
+my $called2 = 0;
+
+sub HasMethod1::new {$called1 ++}
+ @HasMethod1::ISA = qw [Tie::Scalar];
+ @InheritHasMethod1::ISA = qw [HasMethod1];
+
+sub HasMethod2::TIESCALAR {$called2 ++}
+ @HasMethod2::ISA = qw [Tie::Scalar];
+ @InheritHasMethod2::ISA = qw [HasMethod2];
+
+my $r1 = eval {tie my $foo => "InheritHasMethod1"; 1};
+my $r2 = eval {tie my $foo => "InheritHasMethod2"; 1};
+
+ok $r1 && $called1, "inheriting new() does not croak";
+ok $r2 && $called2, "inheriting TIESCALAR() does not croak";