class methods

Discussion in 'Perl Misc' started by Matija Papec, Sep 23, 2003.

  1. Matija Papec

    Matija Papec Guest

    I have situation where /class method/ can be called inside and outside of
    package so I have to know when to throw away the first argument. I found
    that

    shift if $_[0] eq __PACKAGE__;

    should work, but is there a better way to distinguish inside and outside
    calls?


    --
    Matija
    Matija Papec, Sep 23, 2003
    #1
    1. Advertising

  2. [posted & mailed]

    On Tue, 23 Sep 2003, Matija Papec wrote:

    >I have situation where /class method/ can be called inside and outside of
    >package so I have to know when to throw away the first argument. I found
    >that
    >
    >shift if $_[0] eq __PACKAGE__;
    >
    >should work, but is there a better way to distinguish inside and outside
    >calls?


    You could cheat with caller(). If the file of the caller of the function
    is the same file the package is defined in, then you don't need to shift.
    You could even just check if the PACKAGE the caller is in is the same as
    the current package.

    I assume you mean that you have code like so:

    package Foo;

    sub this {
    ...
    }

    sub that {
    this(...);
    }

    and

    package Bar;

    Foo->this(...);

    I would suggest that you NOT call a METHOD as a FUNCTION. But if you are
    going to, then the caller() trick should be sufficient:

    sub this {
    shift @_ if (caller)[0] eq __PACKAGE__;
    ...
    }

    --
    Jeff Pinyan RPI Acacia Brother #734 2003 Rush Chairman
    "And I vos head of Gestapo for ten | Michael Palin (as Heinrich Bimmler)
    years. Ah! Five years! Nein! No! | in: The North Minehead Bye-Election
    Oh. Was NOT head of Gestapo AT ALL!" | (Monty Python's Flying Circus)
    Jeff 'japhy' Pinyan, Sep 24, 2003
    #2
    1. Advertising

  3. In article <>,
    Matija Papec <> wrote:

    > I have situation where /class method/ can be called inside and outside of
    > package so I have to know when to throw away the first argument. I found
    > that
    >
    > shift if $_[0] eq __PACKAGE__;
    >
    > should work, but is there a better way to distinguish inside and outside
    > calls?


    What do you mean by inside and outside the package? Are you saying that
    you want to call it as Foo->bar() from outside the package, and just as
    bar() from within the package? I don't think you actually should do
    that, because that makes it impossible for anyone to override bar() if
    they create a subclass of your class.

    If you can throw the first argument away, as what you've written above
    suggests, then I would just always call it as a method. If you're
    calling it from inside the package, just use the $self (or $this)
    pointer you've got from the method you're in. That way inheritance
    works properly.
    --
    Kevin Michael Vail | Dogbert: That's circular reasoning.
    | Dilbert: I prefer to think of it as no loose ends.
    http://www.vaildc.net/kevin/
    Kevin Michael Vail, Sep 24, 2003
    #3
  4. Matija Papec <> wrote in message news:<>...
    > I have situation where /class method/ can be called inside and outside of
    > package so I have to know when to throw away the first argument. I found
    > that
    >
    > shift if $_[0] eq __PACKAGE__;
    >
    > should work, but is there a better way to distinguish inside and outside
    > calls?


    ==untested==
    #get who's calling the method and the method's unnamed arguments
    my ($caller, @args) = @_;
    #return from the method unless the reference of the caller is equal
    #to the PACKAGE name
    return unless ref($caller) eq __PACKAGE__;

    You may want to look over perltoot and perlbot.

    HTH

    Jim
    James Willmore, Sep 24, 2003
    #4
  5. * James Willmore <>:
    > * Matija Papec <> wrote:
    > > I have situation where /class method/ can be called inside and
    > > outside of package so I have to know when to throw away the first
    > > argument. I found that
    > >
    > > shift if $_[0] eq __PACKAGE__;
    > >
    > > should work, but is there a better way to distinguish inside and
    > > outside calls?


    > ==untested==
    > my ($caller, @args) = @_;
    > return unless ref($caller) eq __PACKAGE__;


    This is a bad idea. When you subclass your module, your first argument
    may end up being something very different from __PACKAGE__ (in
    particular, it could be the __PACKAGE__ of a different package).

    Personally, I'd not do this method at all. If it's a class method,
    use it as a class method. If it's a function, use it as a function.
    Don't do both. It just needlessly complicates the code and introduces
    room for errors.



    cheers,
    --
    Iain.
    Iain Truskett, Sep 24, 2003
    #5
  6. Matija Papec

    Tore Aursand Guest

    On Tue, 23 Sep 2003 22:53:50 +0200, Matija Papec wrote:
    > I have situation where /class method/ can be called inside and outside of
    > package so I have to know when to throw away the first argument.


    What do you mean, actually? Do you want to call the call a method's class
    as a function, as in 'MyClass->Foo()'?

    Seems like bad behaviour in my eyes, but then again I've never used
    anything else than this syntax:

    my $MyObject = MyClass->new();
    $MyObject->foo();

    Inside MyClass there's magic hand waving (well, not reall);

    sub foo {
    my $self = shift;
    $self->bar();
    }

    sub bar {
    my $self = shift;
    # dada
    }

    Am I out of scope here? :)


    --
    Tore Aursand <>

    "You know the world is going crazy when the best rapper is white, the best
    golfer is black, France is accusing US of arrogance and Germany doesn't
    want to go to war."
    Tore Aursand, Sep 24, 2003
    #6
  7. Matija Papec

    Matija Papec Guest

    X-Ftn-To: Jeff 'japhy' Pinyan

    Jeff 'japhy' Pinyan <> wrote:
    >I assume you mean that you have code like so:
    > package Foo;
    > sub this {
    > ...
    > }
    > sub that {
    > this(...);
    > }
    >and
    > package Bar;
    > Foo->this(...);


    Yes.

    >I would suggest that you NOT call a METHOD as a FUNCTION. But if you are


    So what to do instead,

    package Foo;
    sub this {
    ...
    }
    sub that {
    $self->this(...);
    }
    package Bar;
    $object->this(...); #is Foo->this() also fine?

    ?

    >"And I vos head of Gestapo for ten | Michael Palin (as Heinrich Bimmler)
    > years. Ah! Five years! Nein! No! | in: The North Minehead Bye-Election
    > Oh. Was NOT head of Gestapo AT ALL!" | (Monty Python's Flying Circus)


    Sure, and the crowd looked like plain English citizens. ;)


    --
    Matija
    Matija Papec, Sep 24, 2003
    #7
  8. Matija Papec

    Matija Papec Guest

    X-Ftn-To: Kevin Michael Vail

    Kevin Michael Vail <> wrote:
    >What do you mean by inside and outside the package? Are you saying that
    >you want to call it as Foo->bar() from outside the package, and just as
    >bar() from within the package?


    Yes.
    > I don't think you actually should do
    >that, because that makes it impossible for anyone to override bar() if
    >they create a subclass of your class.
    >
    >If you can throw the first argument away, as what you've written above
    >suggests, then I would just always call it as a method. If you're
    >calling it from inside the package, just use the $self (or $this)
    >pointer you've got from the method you're in. That way inheritance
    >works properly.


    So basicaly it would be safest to call Foo()
    $self->Foo(); within the package, and
    SomeClass->Foo(); from other packages?



    --
    Matija
    Matija Papec, Sep 24, 2003
    #8
  9. Matija Papec

    Matija Papec Guest

    X-Ftn-To: Tore Aursand

    Tore Aursand <> wrote:
    >> I have situation where /class method/ can be called inside and outside of
    >> package so I have to know when to throw away the first argument.

    >
    >What do you mean, actually? Do you want to call the call a method's class
    >as a function, as in 'MyClass->Foo()'?


    Yes.

    >Seems like bad behaviour in my eyes, but then again I've never used
    >anything else than this syntax:
    >
    > my $MyObject = MyClass->new();
    > $MyObject->foo();


    Even in cases when method isn't directly manipulating $MyObject but
    impacting a whole class?

    >Inside MyClass there's magic hand waving (well, not reall);
    >
    > sub foo {
    > my $self = shift;
    > $self->bar();
    > }
    >
    > sub bar {
    > my $self = shift;
    > # dada
    > }
    >
    >Am I out of scope here? :)


    I think you're fine. :)


    --
    Matija
    Matija Papec, Sep 24, 2003
    #9
  10. Matija Papec

    Tore Aursand Guest

    On Wed, 24 Sep 2003 18:55:38 +0200, Matija Papec wrote:
    >> Seems like bad behaviour in my eyes, but then again I've never used
    >> anything else than this syntax:
    >>
    >> my $MyObject = MyClass->new();
    >> $MyObject->foo();


    > Even in cases when method isn't directly manipulating $MyObject but
    > impacting a whole class?


    I'll be the first to admit that I'm not an OO guru; I've never been
    teached "proper OO" (if there's such a thing) by a teacher (never attended
    computer science at school), and I might not be familiar with the OO
    terminology. I have, however, been programming "OO-style" for several
    years (since the early 90's). And I've read Damian Conway's excellent
    book about OO programming in Perl. :)

    And:

    There is no such thing as "manipulating a whole class", or - as you
    describe it - impacting a whole class. You never work with _classes_.
    You work with objects, which are _instances of classes_.

    Therefore, IMO, one should avoid calling a class' method without going
    through an instance of the class (even if this is possible in Perl).

    If you're "manipulating a class directly", there is no need for objects
    (or classes) in the first place. You would be dealing with "ordinary Perl
    modules", which _will_ be troublesome in the long run.

    Cutting from an other post from you:

    > So basicaly it would be safest to call Foo()
    > $self->Foo(); within the package [...]


    Yes. If the method 'Foo()' is a member of the same _class_. Please be
    specific when you're talking about packages/modules and/or classes. There
    is a difference.

    > [...] and SomeClass->Foo(); from other packages?


    No. You _should not_ call the class' method directly. You should rather,
    as I've already pointed out, call the method on an instance (ie. an
    object) of the class.


    --
    Tore Aursand <>
    Tore Aursand, Sep 24, 2003
    #10
  11. Matija Papec

    Bart Lateur Guest

    Matija Papec wrote:

    >So basicaly it would be safest to call Foo()
    >$self->Foo(); within the package, and
    >SomeClass->Foo(); from other packages?


    Eh! No. Always use Thisclass->Foo(), (or $obj->Foo()) from within this
    or another package. Caution should be taken that when subclassing, the
    package name might be something else than what is in __PACKAGE__. So
    don't test for string-equality.

    --
    Bart.
    Bart Lateur, Sep 25, 2003
    #11
  12. Matija Papec

    Matija Papec Guest

    On Wed, 24 Sep 2003 23:55:24 +0200, Tore Aursand <>
    wrote:

    >> Even in cases when method isn't directly manipulating $MyObject but
    >> impacting a whole class?

    >
    >I'll be the first to admit that I'm not an OO guru; I've never been
    >teached "proper OO" (if there's such a thing) by a teacher (never attended
    >computer science at school), and I might not be familiar with the OO
    >terminology. I have, however, been programming "OO-style" for several
    >years (since the early 90's). And I've read Damian Conway's excellent
    >book about OO programming in Perl. :)
    >
    >And:
    >There is no such thing as "manipulating a whole class", or - as you
    >describe it - impacting a whole class. You never work with _classes_.
    >You work with objects, which are _instances of classes_.


    I'm no OO expert neither but AFAIR, perl books talk about
    object/instance methods and class methods. Class methods are afaik
    called "static" in c++.
    Matija Papec, Sep 25, 2003
    #12
  13. Matija Papec

    Anno Siegel Guest

    Tore Aursand <> wrote in comp.lang.perl.misc:
    > On Wed, 24 Sep 2003 18:55:38 +0200, Matija Papec wrote:
    > >> Seems like bad behaviour in my eyes, but then again I've never used
    > >> anything else than this syntax:
    > >>
    > >> my $MyObject = MyClass->new();
    > >> $MyObject->foo();

    >
    > > Even in cases when method isn't directly manipulating $MyObject but
    > > impacting a whole class?

    >
    > I'll be the first to admit that I'm not an OO guru; I've never been
    > teached "proper OO" (if there's such a thing) by a teacher (never attended
    > computer science at school), and I might not be familiar with the OO
    > terminology. I have, however, been programming "OO-style" for several
    > years (since the early 90's). And I've read Damian Conway's excellent
    > book about OO programming in Perl. :)
    >
    > And:
    >
    > There is no such thing as "manipulating a whole class", or - as you
    > describe it - impacting a whole class. You never work with _classes_.
    > You work with objects, which are _instances of classes_.


    What makes you say that? Manipulation of the whole class is quite
    possible and that's what class method calls are for. Typical examples
    are language switching, making certain errors fatal, defining defaults
    and lots more. Operations like these *should* be written as class
    methods, because calling them through a specific object would be
    misleading.

    A limiting case is the constructor method (new()), which is generally
    also a class method, though it does pertain to a specific object.

    > Therefore, IMO, one should avoid calling a class' method without going
    > through an instance of the class (even if this is possible in Perl).


    Class methods are generally much rarer than object methods, but they
    have their place.

    > If you're "manipulating a class directly", there is no need for objects
    > (or classes) in the first place.


    What are you thinking of when you say "manipulating a class directly"?
    The examples I gave above certainly make sense in an object oriented
    setting.

    > You would be dealing with "ordinary Perl
    > modules", which _will_ be troublesome in the long run.
    >
    > Cutting from an other post from you:
    >
    > > So basicaly it would be safest to call Foo()
    > > $self->Foo(); within the package [...]

    >
    > Yes. If the method 'Foo()' is a member of the same _class_. Please be
    > specific when you're talking about packages/modules and/or classes. There
    > is a difference.
    >
    > > [...] and SomeClass->Foo(); from other packages?

    >
    > No. You _should not_ call the class' method directly. You should rather,
    > as I've already pointed out, call the method on an instance (ie. an
    > object) of the class.


    A method should normally be either a class method or an object method,
    and should be called accordingly. There is nothing wrong with calling
    a class method through its package name, though this wouldn't depend on
    from where it is called.

    Calling a method as an ordinary sub is something else and should not
    be done, because that would break inheritance.

    Anno
    Anno Siegel, Sep 25, 2003
    #13
  14. Matija Papec

    Tore Aursand Guest

    On Thu, 25 Sep 2003 12:38:29 +0000, Anno Siegel wrote:
    >> There is no such thing as "manipulating a whole class", or - as you
    >> describe it - impacting a whole class. You never work with _classes_.
    >> You work with objects, which are _instances of classes_.


    > What makes you say that?


    I didn't, actually. It was the original poster who used the term
    "impacting a whole class". I took it as he meant "manipulating a whole
    class", which is a term I prefer.

    > Manipulation of the whole class is quite possible and that's what class
    > method calls are for.


    I know that, but I still don't consider that as "manipulating a whole
    class", whatever that _really_ means. :)

    Your examples of using class methods are all fine, but they still define
    the behaviour of the objects of the class (whether they _have been_
    created or _will be_ created).

    Please see my explanation in the context of the current thread; Instead
    of using __PACKAGE__ to find out who's calling who, one should stick with
    the good ol' fashioned OO style in calling methods in other classes. If
    you don't, your design will break as soon as someone subclasses one of the
    classes (as an example).

    > Class methods are generally much rarer than object methods, but they
    > have their place.


    Indeed.

    > Calling a method as an ordinary sub is something else and should not be
    > done, because that would break inheritance.


    Hmm. How many words did I use to say the same? :)


    --
    Tore Aursand <>
    Tore Aursand, Sep 25, 2003
    #14
    1. Advertising

Want to reply to this thread or ask your own question?

It takes just 2 minutes to sign up (and it's free!). Just click the sign up button to choose a username and then you can ask your own questions on the forum.
Similar Threads
  1. E11
    Replies:
    1
    Views:
    4,710
    Thomas Weidenfeller
    Oct 12, 2005
  2. John M. Gabriele
    Replies:
    18
    Views:
    1,142
    Steven Bethard
    Feb 18, 2005
  3. Oltmans
    Replies:
    6
    Views:
    325
    Terry Reedy
    Mar 11, 2009
  4. DG
    Replies:
    3
    Views:
    323
    Terry Reedy
    Jul 22, 2009
  5. Kenneth McDonald
    Replies:
    5
    Views:
    298
    Kenneth McDonald
    Sep 26, 2008
Loading...

Share This Page