Beefy Boxes and Bandwidth Generously Provided by pair Networks
Don't ask to ask, just ask
 
PerlMonks  

Re^2: Overridding subroutines called in private subroutines

by skazat (Chaplain)
on Oct 05, 2008 at 05:53 UTC ( [id://715410]=note: print w/replies, xml ) Need Help??


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

No - that's really helpful - the idea that I can just work within the namespace of the original module in my other script/module, by doin',

{ package Module; # Yadda Yadda, }
I'm guessing the braces localize what I'm doing, so once outside them, I can do whatever I want. Just out of curiousity, would this do the same thing:
package Module; package main; # And now back to our main script...

Replies are listed 'Best First'.
Re^3: Overridding subroutines called in private subroutines
by ikegami (Patriarch) on Oct 05, 2008 at 06:43 UTC

    would this do the same thing:

    If you had been in main initially, yes.

    Speaking of similar things, I didn't answer an earlier question.

    sub Foo::Bar::f {}

    is very similar to

    { package Foo::Bar; sub f {} }

    But the code is compiled in a different package. This affects caller and other things:

    use strict; use warnings; sub Foo::f { our $var; print(__PACKAGE__, "\n"); print("$var\n"); } { package Bar; sub f { our $var; print(__PACKAGE__, "\n"); print("$var\n"); } } $main::var = 'main!'; $Foo::var = 'foo!'; $Bar::var = 'bar!'; Foo::f(); # main # main! Bar::f(); # Bar # bar!
Re^3: Overridding subroutines called in private subroutines
by TGI (Parson) on Oct 06, 2008 at 17:16 UTC
    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

      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

      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

Log In?
Username:
Password:

What's my password?
Create A New User
Domain Nodelet?
Node Status?
node history
Node Type: note [id://715410]
help
Chatterbox?
and the web crawler heard nothing...

How do I use this?Last hourOther CB clients
Other Users?
Others perusing the Monastery: (5)
As of 2024-04-23 19:42 GMT
Sections?
Information?
Find Nodes?
Leftovers?
    Voting Booth?

    No recent polls found