in reply to Re^2: Overridding subroutines called in private subroutines
in thread Overridding subroutines called in private subroutines

I'm guessing the braces localize what I'm doing, so once outside them, I can do whatever I want.

Be careful. The braces ({}) don't localize everything you are doing. The create a scope for your variables, but your package and subroutine declarations remain global. I think the form you used above gives a misleading impression that the package is block scoped.

Update 2: Thanks for the heaping helping of crow, ikegami--I needed it. I was wrong. Dead wrong. See package. I read this wrong information somewhere, failed to check it, and have promulgated bogus information as a result.

{ package Foo; # Foo stuff # goes in here. } sub FooFunc { # This function is Foo::FooFunc! #actually it's not! It is in main. I was wrong. } package main; sub MainFunc { # This function is main::MainFunc. }

That's the reason why I like this approach better:

package Foo; { # Foo stuff # goes in here. } package main; # back in main.

Update: After looking at the module, I'd be inclined to use ikegami's suggestion for using a localized override.

This will minimize the spooky action at a distance factor.

#!/usr/bin/perl use strict; use warnings; package Foo; sub method { routine(); } sub routine { return __PACKAGE__; } package Foo::Bar; our @ISA = qw( Foo ); sub routine { return __PACKAGE__; } sub method { no warnings 'redefine'; # Temporarily override routine() in the parent class. local *Foo::routine = \&routine; # Delegate to parent method. my $self = shift; $self->SUPER::method(@_); } package main; print "Foo: ", Foo->method, "\n"; print "Foo::Bar: ", Foo::Bar->method, "\n"; print "Foo: ", Foo->method, "\n";


TGI says moo

Replies are listed 'Best First'.
Re^4: Overridding subroutines called in private subroutines
by ikegami (Patriarch) on Oct 07, 2008 at 03:55 UTC

    Be careful. The braces ({}) don't localize everything you are doing. The create a scope for your variables, but your package and subroutine declarations remain global.

    No, that's wrong. package is lexically scoped. That's why you don't have to switch it back after a module changes it.

    print(__PACKAGE__, "\n"); { package Foo; print(__PACKAGE__, "\n"); } print(__PACKAGE__, "\n");
    main Foo main
Re^4: Overridding subroutines called in private subroutines
by ikegami (Patriarch) on Oct 07, 2008 at 03:57 UTC

    It's really just a nit, but you're leaking an alias to @Foo::Bar::ISA. I also use BEGIN {} instead of {} inlined modules. I'd write your program as:

    #!/usr/bin/perl use strict; use warnings; BEGIN { package Foo; sub method { routine(); } sub routine { return __PACKAGE__; } } BEGIN { package Foo::Bar; our @ISA = qw( Foo ); sub routine { return __PACKAGE__; } sub method { no warnings 'redefine'; # Temporarily override routine() in the parent class. local *Foo::routine = \&routine; # Delegate to parent method. my $self = shift; $self->SUPER::method(@_); } } print "Foo: ", Foo->method, "\n"; print "Foo::Bar: ", Foo::Bar->method, "\n"; print "Foo: ", Foo->method, "\n";

      Thanks for correcting me regarding package.

      I wanted to clarify the leaking alias nit that you referred to. If I understand the perldoc correctly, I am leaking the alias to @Foo::Bar::ISA because the our declaration creates an alias that persists across the lexical scope. So if I had enclosed the packages in braces, the leak would be prevented.

      I like your approach of using BEGIN blocks to enclose inline modules. It more closely approximates the behavior of useing them from separate files (of course you may need to add an import if you want the full goodness of use). An excellent suggestion. This would have saved me hassles on a few occasions.


      TGI says moo

        This is the leaking to which I was refering:
        $Foo::var = 'foo!'; $Bar::var = 'bar!'; package Foo; our $var; package Bar; print("$var\n"); # foo!
        $Foo::var = 'foo!'; $Bar::var = 'bar!'; { package Foo; our $var; } { package Bar; print("$var\n"); # bar! }