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 :(

      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?

      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.

        Update:

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