Perlers tend to use the convention of using a leading underscore to mark private/protected methods in OO code. However, this has some problems:
It conflates private and protected methods. Private methods being those methods which nobody outside the class has any business calling; protected methods being those which are OK for subclasses to call and potentially override.
When you're writing a subclass, you need to know about all the superclasses' private methods to ensure you don't accidentally override any of them by coincidentally writing a sub with the same name.
Perl 5.18's experimental lexical subs feature can be exploited to create truly private subs. We need to introduce a little syntactic sugar (or perhaps vinegar, depending on how you look at it), to circumvent the fact that lexical subs are not really designed to be called as methods - we use this syntax: $self->${\\&method_name}(@args). (Think of it as a mega-sigil.)
#!/usr/bin/env perl use v5.18; use feature qw(lexical_subs); no warnings qw(experimental); package MyClass { # # Private methods # my sub get_number { my $self = shift; return $self->{number}; } # # Public methods # sub new { my $class = shift; return bless {@_}, $class; } sub say_number { my $self = shift; # Slightly funky syntax for calling a # lexical sub as a private method... say $self->${ \\&get_number }; } } package ChildClass { use base "MyClass"; # # A public method that has the same name as a # private method in the superclass. Note that # the private method will *NOT* get overridden! # Yay! # sub get_number { warn "You're not allowed to get the number!"; } } my $o = ChildClass->new(number => 42); $o->say_number; # works... my $p = MyClass->new(number => 666); $p->get_number; # asplode; it's a private method
Update: I hasten to add that I'm not advocating doing this in production code any time in the near future. But it's an interesting option to think about in years to come.
I'll also point out that a similar thing can be achieved using coderefs in earlier versions of Perl:
my $private_method = sub { ...; }; $self->$private_method(@args);
|
---|