in reply to OO modules

An OO module *is* a library. The words module and library can be used for each other interchangeably. For OO, you must have a module/library file. This file contains the "class" that your objects will be blessed into. To make things more confusing, a class is called a "Package" in Perl. In the below example, you'll see what I mean.

new() is a class method that instantiates, configures and returns an object of the class. In its most basic form, it can look like this: sub new {bless {}, shift;}. That blesses a hash reference into the class, and implicitly returns the new object. You can use any name for this method as you like, but the de-facto unwritten rule standard is and always has been new(). I know some devs who use init() or other things, but because of the unforced standard, I always expect to see a new() method if I'm looking at someone elses code.

bless() is the class method that actually makes a standard perl reference type an object of your class. It provides you the ability to call methods against it etc. This method is internal to perl, and can not be changed. You can bless any reference type you want. The de-facto standard is a hash reference, but there are a few reasons why you'd want to use other types. Hashes make it easy to use the attributes/members of the object (example code below unverified and untested):

package My::Class; use warnings; use strict; use Carp qw(croak); sub new { my ($class, %args) = @_; my $self = bless {%args}, $class; $self->_validate_args; return $self; } sub swear { my ($self, $word) = @_; croak "swear() needs word param sent in" if ! defined $word; if ($self->can_swear) { print "$word\n"; } } sub can_swear { # getter/setter, and returns the value of the 'can_swear' attribut +e. # This attribute determines whether the object is allowed to use f +oul language my ($self, $can_swear) = @_; $self->{can_swear} = $can_swear if defined $can_swear; # If can_swear wasn't set via this method, or wasn't set # within the %args parameters hash to new(), we default # to not allowing the object to swear return $self->{can_swear} // 0; } sub _validate_args { my ($self) = @_; if (! exists $self->{not_provided_in_new_args}) { # do stuff } }

Script:

use My::Class; my %args = ( swear => 1, emphasis => 1, }; my $object = My::Class->new(%args); $object->swear('damnit');

$self is the actual object itself. We (pretty well) always refer to an object of the class as self while working with it within the class. Again, this is not a hard rule, but just stick with it so others reading your code won't be confused.

When you call an object's method, the object is inserted at the beginning of the parameter list into the method. This happens automatically behind the scenes. So this:

$object->swear('damnit');

Is converted to:

swear($object, 'damnit');

When our swear() method is called, we shift off the object and the swear word into the variables $self and $word. We're then able to call other methods or do other work on the $self object. Here's what the above looks like when I display the contents of the @_ array in the method. The @_ array contains the full parameter list to the method:

$VAR1 = [ bless( {}, 'My::Class' ), 'damnit', ];

Another note... methods that begin with an underscore are "private" methods. Ones that typically do maintenance and validation type work, or are chunks of larger public methods that perform specific pieces of functionality. These methods are not designed for use by the users of your objects. An example is the _validate_args() in the above example. This rule is also unenforced, but is a very long-standing standard. Try not to use common names for these, use long, descriptive ones.

Replies are listed 'Best First'.
Re^2: OO modules
by shmem (Chancellor) on Dec 29, 2020 at 09:09 UTC
    An OO module *is* a library. The words module and library can be used for each other interchangeably. For OO, you must have a module/library file. This file contains the "class" that your objects will be blessed into. To make things more confusing, a class is called a "Package" in Perl.

    To nitpick a bit on that: it is in fact the other way round. First comes the namespace which is called a package. It is declared with the keyword package followed by the package name, optionally followed by a block containing all what belongs to that namespace. Without that block which defines it, the packages scope ends when another namespace (or package) is declared, when the enclosing scope ends or at end of file. This namespace can be OO, but must not be. Any number of packages may be declared in whatever perl code, and packages can be switched within.

    For any collection of functions to be a module or library, OO or not, it must be contained in its own file - otherwise it is not modular.
    For a library or module to be OO, it must declare a namespace and its functions must take into account that their first argument is either an object (a reference "blessed" into the class, i.e. tagged with it) or the class itself (which happens to be the package name).

    When useing a module via its namespace (package) name, it must be contained in a file relative to any directory in perls include path, where its relative path is the package name with .pm appended, and the double colons :: within are substituted by the directory path separator. But require provides more rope.

    So, package, module and OO - or namespace, library and namespace aware function collections - are loosely coupled concepts in the sense that each can be used on its own. It is perfectly feasible to write a program which uses OO but doesn't use any module, where all classes are lumped together into one file - in which case it isn't modular. This is what App::FatPacker does.

    The path resolution thingy of included files is a different thing, explained in use and require. A package directive within isn't mandatory if it isn't OO, its last statement must just yield some true value:

    # file Useless/Nothing.pm 1;

    This, while being useless, compiles and adds a key/value pair to %INC but doesn't create/add the namespace Useless::Nothing. Any symbols defined in such a file without explicit package directive are hooked into the package in scope where the use occurs.

    Oh, and

    bless() is the class method that actually makes a standard perl reference type an object of your class.

    bless() is a function, and a method of package CORE. So to work as a method, the invoking variable needs to be blessed into package CORE first...

    qwurx [shmem] ~> perl -E '$foo = bless {}, "CORE"; $foo->bless("blorf" +); say $foo' blorf=HASH(0x1e53e78) qwurx [shmem] ~> perl -e '$foo = bless {}, "blorf"; $foo->bless("CORE" +); say $foo' Can't locate object method "bless" via package "blorf" at -e line 1. qwurx [shmem] ~> perl -e '$foo = {}; $foo->bless("blorf"); say $foo' Can't call method "bless" on unblessed reference at -e line 1.

    Which also means that you can have a class method bless, but that's somewhat useless, except for obfuscation and other sophisticated use cases:

    package Whatever; sub bless { my ($object, $class) = @_; return bless $object, $class; }

    That would be a method for object migration ;)

    perl -le'print map{pack c,($-++?1:13)+ord}split//,ESEL'