Perl doesn't really like the concept of final
subroutines, but you can try. Given the following:
BEGIN {
package final;
$INC{'final.pm'}++;
use Variable::Magic qw(wizard cast);
sub import {
my (undef, $symbol) = @_;
my ($stash, $name) = $symbol =~ /(.+::)(.+)/;
unless ($stash) {
$stash = caller().'::';
$name = $symbol;
$symbol = $stash.$name;
}
no strict 'refs';
my $glob = \*$symbol;
my $code = \&$glob;
my ($seen, @last);
cast %$stash, wizard store => sub {
if ($_[2] eq $name and $code != \&$glob) {
print "final subroutine $symbol was redefined ".
"at $last[1] line $last[2].\n" unless $seen++
}
@last = caller
}
}
}
You could then write:
use warnings;
use strict;
{
package Foo;
sub hello {print "HI"}
use final 'hello';
}
package main;
no warnings;
sub Foo::hello {print "bye"}
Foo::hello();
Which will print something like:
final subroutine Foo::hello was redefined at filename.pl line 9.
bye
The warning is printed right before the redefined subroutine is first called, not when it is actually redefined (due to limitations of the way perl and Variable::Magic
work). But it is better than nothing.
The no warnings;
is in there since perl will normally throw a warning when subroutines are redefined. So maybe telling your users to use warnings
is good enough. As Larry has said:
Perl doesn't have an infatuation with enforced privacy. It would
prefer that you stayed out of its living room because you weren't
invited, not because it has a shotgun.