in reply to Module provides both of functional interface and object-oriented one

If you forget about exporting your functions, you can try this:

package Foo; # constructor sub new { my $klass = shift; # maybe take arguments from @_ my $self = bless {}, $klass; return $self; } sub bar { my $self = shift; my ($param1, $param2) = @_; if (ref $self) { # we are an object instance print "hey, I'm an object\n"; } return ($param1 == $param2); } # and how to use it package main; # procedural Foo->bar(6 * 9, 42); # OO my $f = Foo->new(); $f->bar(15 * 17, 255);
  • Comment on Re: Module provides both of functional interface and object-oriented one
  • Download Code

Replies are listed 'Best First'.
Re^2: Module provides both of functional interface and object-oriented one
by anazawa (Scribe) on Feb 17, 2012 at 06:20 UTC
    Thanks for your suggestion. I think your code works correctly. Frankly speaking, I'm working on Blosxom::Header inspired by Plack::Util::headers. I'm trying to wrap existent subroutines in an object. Although there are many ways to derive OO interface from procedual one, it's difficult to choose one of them :(

      The basic idea behind the code is: Foo->bar(@_) is really a nice way of saying Foo::bar("Foo", @_) and $f->bar(@_) is Foo::bar($f, @_). After that, ref $self returns false for the string "Foo" (as it is not a reference) but the class name for the object.

      I don't think it's a bad approach at all, but it will break existing subroutine-using code unless you somehow sniff what type the first argument is.

      Since your functional interface already requires passing a reference on every call, I don't actually see why anyone would prefer to use it. Personally, if your module is not in too wide use yet, I would choose to retire it and tell the people depending on your module to change their code.

        I agree with you. According to your idea, users don't need to pass a reference subroutines on every call:
        use Blosxom::Header; # procedural interface my $value = Blosxom::Header->get($key); my $bool = Blosxom::Header->exists($key); Blosxom::Header->set($key => $value); Blosxom::Header->remove($key); # OO interface my $h = Blosxom::Header->new(); my $value = $h->get($key); my $bool = $h->exists($key); $h->set($key => $value); $h->remove($key);
        Nobody uses my module except for me :) But I belive this module should exist.


        I noticed that it's not necessary to implement OO interface any more in this case.

      On the other hand, there's nothing that forbids you from creating wrappers which you can export. Adding to my previous code:

      @EXPORT_OK = qw/get_bar/; sub get_bar { my $var = shift; # your $blosxom::header hashref bar($var, @_); }
        If a module looks as follows:
        package Foo; @EXPORT_OK = qw(get_foo); sub new { # constructer } sub get { # for OO interface } sub get_foo { # for procedural interface } 1;
        users may write as follows:
        $o = Foo->new(); $o->get($key); # of cource, $value $o->get_foo($key); # what's this?
        If users choose OO interface, they shouldn't be able to call 'get_foo' method. How can I solve this problem?