Beefy Boxes and Bandwidth Generously Provided by pair Networks
good chemistry is complicated,
and a little bit messy -LW
 
PerlMonks  

How do I make object methods callable as non-OO functions?

by trammell (Priest)
on Jun 24, 2004 at 21:34 UTC ( [id://369493]=perlquestion: print w/replies, xml ) Need Help??

trammell has asked for the wisdom of the Perl Monks concerning the following question: (object-oriented programming)

For example, say I have a class 'Foo' that is used thusly:
use Foo; my $f = Foo->new(%args); my $g = $f->frobnicate;
but for some Very Good Reason, we want to be able to call it in a more procedural fashion:
use Foo 'frobnicate'; my $g = frobnicate($args);
Is there a good way of doing this? Is there a good reason not to do this?

Originally posted as a Categorized Question.

Replies are listed 'Best First'.
Re: How do I make object methods callable as non-OO functions?
by jhourcle (Prior) on Mar 25, 2005 at 03:51 UTC

    I use the following at the beginning of the sub, so I can still use $self, and someone can override the functions in a derived class, if need be. (it won't work with your exact calling syntax though, as it's mostly for items that don't require values from the actual object).

    sub function_name { # for a function call my $self = __PACKAGE__; # for a method call $self = shift if UNIVERSAL::isa( $_[0], __PACKAGE__ ); ... }

    You could also write do the shorter, more efficient, but potentially more confusing :

    sub function_name { my $self = UNIVERSAL::isa( $_[0], __PACKAGE__ ) ? shift : __PACKAGE__; ... }
      CGI.pm does something simliar, except with a generic sub.
      sub self_or_default { return @_ if defined($_[0]) && (!ref($_[0])) &&($_[0] eq 'CGI'); unless (defined($_[0]) && (ref($_[0]) eq 'CGI' || UNIVERSAL::isa($_[0],'CGI')) # slightl +y optimized for common case ) { $Q = $CGI::DefaultClass->new unless defined($Q); unshift(@_,$Q); } return wantarray ? @_ : $Q; }
      Then they use it like this:
      sub url_param { my ($self,@p) = self_or_default(@_); my $name = shift(@p); return undef unless exists($ENV{QUERY_STRING}); ...
Re: How do I make object methods callable as non-OO functions?
by cosimo (Hermit) on Jun 30, 2004 at 12:09 UTC
    Probably, what you want is something like:
    package Foo; sub new { # A noop constructor bless {}, shift; } sub frobnicate { my($self, @args) = @_; unless($self eq 'Foo' || (ref $self && $self->isa('Foo'))) { unshift @args, $self; undef $self; } # Now $self is available only if you have an OO call # List of @args is always the same return join(', ', @args). "\n"; }
    and use it in the following way:
    my $f = Foo->new(); print $f->frobnicate('my','args'); # or print Foo::frobnicate('my','args'); # or even print Foo->frobnicate('my','args');
    Beware, though that doing something like $self->isa('Foo') breaks inheritance mechanisms and IMHO it is a Bad Thing (tm).

    As usual, perl "gives you enough rope to hang yourself", which is a Good Thing (tm) :-)

Re: How do I make object methods callable as non-OO functions?
by Anonymous Monk on Jun 25, 2004 at 21:58 UTC
    use Exporter; @ISA = ('Exporter'); @EXPORT = @EXPORT_OK = qw(frobnicate);
    frobnicate is then available both as an OO-subroutine and a procedural one...

Log In?
Username:
Password:

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

How do I use this?Last hourOther CB clients
Other Users?
Others having a coffee break in the Monastery: (5)
As of 2024-04-23 22:31 GMT
Sections?
Information?
Find Nodes?
Leftovers?
    Voting Booth?

    No recent polls found