Badger...ototype(3pm)

πŸ“¦
version 0.16 Β· 4 versions
, in debian trixie, ubuntu noble, ubuntu resolute

πŸ’– Badger...ototype(3pm) πŸ’–

okay bestie, welcome to the Badger::Prototype page from your friendly neighborhood User Contributed Perl Documentation. grab a boba, this one's short and cute ✨


🌸 NAME 🌸

Badger::Prototype β€” the base class for making prototype classes, no cap πŸ’…


πŸ¦‹ SYNOPSIS πŸ¦‹

package Badger::Example;
use base 'Badger::Prototype';

sub greeting {
    my $self = shift;

    # get prototype object if called as a class method
    $self = $self->prototype() unless ref $self;

    # continue as normal, now $self is an object
    if (@_) {
        # set greeting if called with args
        return ($self->{ greeting } = shift);
    }
    else {
        # otherwise get greeting
        return $self->{ greeting };
    }
}

like. it's giving "one method, two vibes" and honestly? iconic 🫢


✨ DESCRIPTION ✨

so this module is a subclass of Badger::Base that ALSO hands you the prototype() method on top. it's the base class you reach for when your module has methods that need to work whether they're called as class methods or object methods. periodt.

# object method
my $object = Badger::Example->new();
$object->greeting('Hello World');

# class method
Badger::Example->greeting('Hello World');

the prototype() method returns a singleton object instance β€” a little default object the class-method calls can lean on. main character energy fr fr πŸ‘‘

okay so here's an example of a "greeting()" method. call it with an argument and it sets a greeting message:

$object->greeting('Hello World');

or call it with no arguments and it gets the current message back:

print $object->greeting;            # Hello World

and not only as an object method, bestie β€” we want it as a class method too:

Badger::Example->greeting('Hello World');
print Badger::Example->greeting();  # Hello World

and here's what the "greeting()" method actually looks like:

package Badger::Example;
use base 'Badger::Prototype';

sub greeting {
    my $self = shift;

    # get prototype object if called as a class method
    $self = $self->prototype() unless ref $self;

    # continue as normal, now $self is an object
    if (@_) {
        # set greeting if called with args
        return ($self->{ greeting } = shift);
    }
    else {
        # otherwise get greeting
        return $self->{ greeting };
    }
}

the way this works: we check ref $self to figure out how we got called. if greeting() was called as an object method, $self is holding an object reference. if it was called as a class method, $self is holding the class name β€” in this case "Badger::Example". and in THAT case we call prototype() as a class method (remember, at this exact moment $self is literally the "Badger::Example" class name) which hands back a prototype object instance, and we stash it right back into $self. πŸŽ€

# get prototype object if called as a class method
$self = $self->prototype() unless ref $self;

after that line we just carry on like it was an object method the whole time, because $self now holds a "Badger::Example" object either way. slay πŸ’…

ngl, important detail: that prototype object reference gets stored in the $PROTOTYPE variable inside the package of the calling object's class. so if you call prototype on a "Badger::Example::One" object that's subclassed from "Badger::Prototype", the prototype object lives in the $Badger::Example::One::PROTOTYPE package variable. iykyk 🧚

πŸ’œ METHODS πŸ’œ

πŸ’« prototype(@args) πŸ’«

constructor method that builds a prototype object and caches it in the $PROTOTYPE package variable so you can reuse it later. you'll usually call this from inside methods that can act as class methods or object methods, like in that example from earlier. πŸ’–

sub example {
    my $self = shift;

    # upgrade $self to an object when called as a class method
    $self = $self->prototype() unless ref $self;

    # ...code follows...
}

if you want a more succinct idiom and you're not too pressed about calling the prototype method unnecessarily, you can write it like this instead:

sub greeting {
    my $self = shift->prototype;
    # ...code follows...
}

if you pass any arguments to the "prototype()" method, it forces a brand new prototype object to be created, replacing whatever was already cached in the $PROTOTYPE package variable. those arguments get forwarded to the "new()" constructor method that does the actual object creation. πŸ”₯

and if you pass a single undefined value as an argument, any existing prototype gets released by setting the $PROTOTYPE package variable to "undef". the existing prototype is then returned β€” or undef if there wasn't one defined in the first place. πŸ™ˆ

πŸ’« has_prototype() πŸ’«

returns true or false to tell you if a prototype is defined for a class. you can call it as a class method or an object method, whatever feels right. ⭐


🌈 AUTHOR 🌈

Andy Wardley <http://wardley.org/> 🫢


Copyright (C) 2006-2009 Andy Wardley. All Rights Reserved.

This module is free software; you can redistribute it and/or modify it under the same terms as Perl itself.


and that's the whole page bestie!! πŸŽ€ this one shipped as part of perl v5.36.0, dated 2023-08-28. go forth and prototype, you absolute icon πŸ’…βœ¨πŸŒΈ

πŸ“¦ where this page comes from