in reply to Re: Perl OO: switch package context.
in thread Perl OO: switch package context.

Oooh yes. Even more scary:
use constant Class => 'My::Package::Class'; my $object = Class->new(...);
If you do that, I shall come over and slap you though. {grin}

-- Randal L. Schwartz, Perl hacker
Be sure to read my standard disclaimer if this is a reply.


update: And yes, I already slapped Ovid for Aliased in a previous discussion.

Replies are listed 'Best First'.
Re^3: Perl OO: switch package context.
by japhy (Canon) on May 14, 2005 at 13:21 UTC
    I said I wouldn't show it, but I suppose I will since you're sharing...
    sub UNIVERSAL::new { my $class = caller() . "::" . shift; $class->new(@_); }
    It works by catching calls to new() on a package that doesn't have a new() defined. We're expecting this to mean the package doesn't really exist, and is instead the suffix of the full package name. We get the beginning of the package name from the package we called it in (caller()) and join it with the suffix (the first argument to new()), and use that as the package name. Example:
    package A::B::C; sub new { print "A::B::C new @_\n" } package A::B; C->new(10); # C->new calls UNIVERSAL::new('C', 10) # caller() returns 'A::B' (the package we were in) # UNIVERSAL::new calls A::B::C->new(10)
    I'll take my 20 lashes now.

    (Double update: merlyn pointed out in a reply that my code is still an infinite loop, so I've readjusted it.) Update: to prevent infinite loops, I changed the code to:

    sub UNIVERSAL::new { my $pkg = shift; my ($class, $file, $line) = caller; my $class = "${class}::$pkg"; my $new = $class->can('new'); return $class->$new(@_) if $new != \&UNIVERSAL::new; die qq{Can't locate object method "new" via packages $pkg or $class +at $file line $line.\n};
    Gawrsh, now it's lookin' purty.

    Jeff japhy Pinyan, P.L., P.M., P.O.D, X.S.: Perl, regex, and perl hacker
    How can we ever be the sold short or the cheated, we who for every service have long ago been overpaid? ~~ Meister Eckhart
      my $new = $class->can('new'); return $class->$new(@_) if $new;
      How does that prevent infinite loops? Won't "can" return the entry in UNIVERSAL now? What you should do is set local $I_AM_INSIDE_UNIVERSAL_NEW = 1, and then detect that for a loopback detection.

      -- Randal L. Schwartz, Perl hacker
      Be sure to read my standard disclaimer if this is a reply.

        Ah, my bad. I hadn't even created the package, so can() returned false. I could use your method, but I'll opt for:
        return $class->$new(@_) if $new != \&UNIVERSAL::new;

        Jeff japhy Pinyan, P.L., P.M., P.O.D, X.S.: Perl, regex, and perl hacker
        How can we ever be the sold short or the cheated, we who for every service have long ago been overpaid? ~~ Meister Eckhart
Re^3: Perl OO: switch package context.
by Ovid (Cardinal) on May 14, 2005 at 16:56 UTC

    Hmm ... I remember your objection/caution about using aliased when you had that contract, but I don't recall a thread about it. Other than the obvious problem of accidentally overwriting a namespace, why do you object to this? What am I missing here?

    Cheers,
    Ovid

    New address of my CGI Course.

Re^3: Perl OO: switch package context.
by Joost (Canon) on May 14, 2005 at 13:23 UTC