Beefy Boxes and Bandwidth Generously Provided by pair Networks
laziness, impatience, and hubris

OOP private functions

by zeltus (Sexton)
on Feb 13, 2014 at 09:50 UTC ( #1074774=perlquestion: print w/ replies, xml ) Need Help??
zeltus has asked for the wisdom of the Perl Monks concerning the following question:

When writing a traditional OOP package, do private functions need to be part of the object?

By that, I mean, accessors tend to look like

sub happy_birthday { my $self = shift; return $self->age( $self->age() + 1 ); }

(it's that there "my $self = shift;" bit I am looking at with a jaundiced eye)

If an accessor wants to use a private function (say, _topsecretsort() ), are there any pros and cons or conventions in just making it an "ordinary" function, or should it be a method, as per the accessor methods>

I can't seem to find anything on this... everyone seems to do one or the other. Is there a perceived general rule of thumb for said private functions?


Comment on OOP private functions
Download Code
Re: OOP private functions
by tobyink (Abbot) on Feb 13, 2014 at 10:17 UTC

    Generally speaking, you will want to call the _topsecretsort sub as a method, not as a function. The primary reason would be that _topsecretsort may need access to $self (perhaps so that it can call further methods), and even if the current implementation of _topsecretsort does not require access to $self, future rewrites of it may.

    That said, I'd hesitate to call _topsecretsort a "private method". It is not a private method in the same sense that programming languages with true privacy would understand it. _topsecretsort can be called and overridden by superclasses, and by code entirely external to the class. I think the best term for this sort of sub would be an "undocumented method", not a "private method".

    (In fact, getting back to whether the sub should be called as a function or as a method... the one advantage of calling the sub as a function instead of a method, would be that it would prevent superclasses from accidentally or deliberately overriding it.)

    The best way to approximate true private methods in Perl is to use coderefs:

    my $_topsecretsort = sub { my $self = shift; my ($x, $y) = @_; return 42; }; sub count_sorted_foobars { my $self = shift; my @results = $self->$_topsecretsort('foo', 'bar'); return scalar(@results); }

    In Moops I've even created a shortcut for this pattern:

    use Moops; class FooBar { method my $_topsecretsort ($x, $y) { return 42; } method count_sorted_foobars () { my @results = $self->$_topsecretsort('foo', 'bar'); return scalar(@results); } } say FooBar->new->count_sorted_foobars;
    use Moops; class Cow :rw { has name => (default => 'Ermintrude') }; say Cow->new->name
Re: OOP private functions
by sundialsvc4 (Monsignor) on Feb 13, 2014 at 12:13 UTC

    The Perl language, AFAIK, doesn’t really have the notion of “a private method.”   The convention that I have generally seen used is that methods which are considered to be private have names beginning with an underscore, e.g. sub _private { ...   But this is only a human convention.

    I also think that it is generally advisable to let these things be methods, partly to be consistent within the package.   (After all, if they are subs that are defined within a package that has been blessed (i.e. “a Perl ‘object’,”), then they certainly can and might be called as a method, so they should probably just expect it.   Basically, that just means expecting “yourself” (e.g. $self) to be arriving as the first, implied parameter.   But, if you consistently do things in that way, you will be doing what I think most of your colleagues and successors will have come to expect.

    Now, let us say that you do have a slew of pure-Utility routines.   Every app does.   So, what I would do (have generally seen done, and copied it ...) in that case is to define a Utility package (by some app-specific name), and, furthermore, to use specific subroutines out of it.   For example:

    use My_Utilities qw(foo bar bletch)

    Or, maybe, declare that none of the routines are to be imported, and then reference the ones that you want with a fully-qualified name, like this:

    use MyUtilities ( )
    my $x = MyUtilities::bletch();

    The idea here being that, since My_Utilities might have a whole bunch of generally-unrelated and commonly-named functions, you want to make it clear to your Gentle Reader (and to Perl) exactly where those functions can be found.   You do this just in case someone who follows you needs to know what bletch() does, and just in case you’ve been smooshed by a bread-truck (or, been hired by Google ... let’s paint happy-trees here ...) since that time.   Geeks would say, “to avoid polluting the local namespace.”

Log In?

What's my password?
Create A New User
Node Status?
node history
Node Type: perlquestion [id://1074774]
Approved by tobyink
Front-paged by tobyink
and the web crawler heard nothing...

How do I use this? | Other CB clients
Other Users?
Others lurking in the Monastery: (13)
As of 2014-08-27 19:33 GMT
Find Nodes?
    Voting Booth?

    The best computer themed movie is:

    Results (250 votes), past polls