Test2:...shBase(3pm)

πŸ’– NAME πŸ’–

Test2::Harness::Util::HashBase β€” build hash-based classes, bestie. that's the whole job. slay.


✨ SYNOPSIS ✨

okay so first up, here's a whole class:

package My::Class;
use strict;
use warnings;

# Generate 3 accessors
use Test2::Harness::Util::HashBase qw/foo -bar ^baz <bat >ban +boo/;

# Chance to initialize defaults
sub init {
    my $self = shift;    # No other args
    $self->{+FOO} ||= "foo";
    $self->{+BAR} ||= "bar";
    $self->{+BAZ} ||= "baz";
    $self->{+BAT} ||= "bat";
    $self->{+BAN} ||= "ban";
    $self->{+BOO} ||= "boo";
}

sub print {
    print join ", " => map { $self->{$_} } FOO, BAR, BAZ, BAT, BAN, BOO;
}

then you subclass it, as one does πŸ¦‹

package My::Subclass;
use strict;
use warnings;

# Note, you should subclass before loading HashBase.
use base 'My::Class';
use Test2::Harness::Util::HashBase qw/bub/;

sub init {
    my $self = shift;

    # We get the constants from the base class for free.
    $self->{+FOO} ||= 'SubFoo';
    $self->{+BUB} ||= 'bub';

    $self->SUPER::init();
}

and then you literally just use it:

package main;
use strict;
use warnings;
use My::Class;

# These are all functionally identical
my $one   = My::Class->new(foo => 'MyFoo', bar => 'MyBar');
my $two   = My::Class->new({foo => 'MyFoo', bar => 'MyBar'});
my $three = My::Class->new(['MyFoo', 'MyBar']);

# Readers!
my $foo = $one->foo;    # 'MyFoo'
my $bar = $one->bar;    # 'MyBar'
my $baz = $one->baz;    # Defaulted to: 'baz'
my $bat = $one->bat;    # Defaulted to: 'bat'
# '>ban' means setter only, no reader
# '+boo' means no setter or reader, just the BOO constant

# Setters!
$one->set_foo('A Foo');

#'-bar' means read-only, so the setter will throw an exception (but is defined).
$one->set_bar('A bar');

# '^baz' means deprecated setter, this will warn about the setter being
# deprecated.
$one->set_baz('A Baz');

# '<bat' means no setter defined at all
# '+boo' means no setter or reader, just the BOO constant

$one->{+FOO} = 'xxx';

periodt πŸ’…


🌸 DESCRIPTION 🌸

so this package is the one that generates classes built on hashrefs. use it and you get a new() method, plus all the accessors you ask for. the generated accessors are getters, and set_ACCESSOR setters get generated for you too. you also get constants for every accessor (all caps, bestie) that hand you back the key into the hash for that accessor. single inheritance is supported too. no cap.


πŸŽ€ THIS IS A BUNDLED COPY OF HASHBASE πŸŽ€

this is a bundled copy of Object::HashBase. the file was generated using the /home/exodist/perl5/perlbrew/perls/main/bin/hashbase_inc.pl script. iconic of it, honestly.


πŸ‘‘ METHODS πŸ‘‘

🫢 PROVIDED BY HASH BASE 🫢

  • $it = $class->new(%PAIRS)
  • $it = $class->new(\%PAIRS)
  • $it = $class->new(\@ORDERED_VALUES)

creates a new instance. that's the vibe.

HashBase will not export new() if there's already a new() method somewhere in your packages inheritance chain. it knows. it's not gonna step on that.

and if you don't want this method at all? you can define your own β€” you just have to declare it before loading Test2::Harness::Util::HashBase.

package My::Package;

# predeclare new() so that HashBase does not give us one.
sub new;

use Test2::Harness::Util::HashBase qw/foo bar baz/;

# Now we define our own new method.
sub new { ... }

this makes it so that HashBase sees you've got your own new() method. alternatively you can define the method before loading HashBase instead of just declaring it, but that scatters your use statements around, which is lowkey messy.

the most common way to make an object is passing in key/value pairs, where each key is an attribute and each value is what you want assigned to that attribute. no checking is done to verify the attributes or values are valid β€” you can do that in init() if you feel like it.

if you'd rather, you can pass in a hashref instead of pairs. when you do that, the hashref gets copied, and the copy gets returned blessed as an object. there is no way to ask HashBase to bless a specific hashref. it said no 🚫

sometimes an object only has like 1 or 2 attributes, and a hashref is just too much typing for your taste. in those cases you can pass in an arrayref with only values. the values get assigned to attributes in the order the attributes were listed. when inheritance is involved, the attributes from parent classes come before the subclasses. oldest first, as they should πŸ’–

🧚 HOOKS 🧚

  • $self->init()

your chance to set some default values on your fields. the only argument is $self with its indexes already set from the constructor.

Note: Test2::Harness::Util::HashBase checks for an init using $class->can('init') during construction. It DOES NOT call can() on the created object. also note the result of that check is cached β€” it's only ever checked once, the first time an instance of your class is created. so if you add an init() method AFTER the first construction, it will just be ignored. rude, but that's the deal 😭

🌈 ACCESSORS 🌈

πŸ’œ READ/WRITE πŸ’œ

to generate accessors you list them when you use the module:

use Test2::Harness::Util::HashBase qw/foo/;

this generates the following subs in your namespace:

  • foo() β€” getter, used to get the value of the "foo" field.
  • set_foo() β€” setter, used to set the value of the "foo" field.
  • FOO() β€” constant, returns the field "foo"'s key into the class hashref. subclasses will also get this function as a constant, not simply a method β€” that means it gets copied into the subclass namespace. the main reason for these constants is helping you dodge spelling mistakes and similar typos. it will not help you if you forget to prefix the + though. we've all been there πŸ™ˆ

πŸ¦‹ READ ONLY πŸ¦‹

use Test2::Harness::Util::HashBase qw/-foo/;
  • set_foo() β€” throws an exception telling you the attribute is read-only. this got exported to override any active setters for the attribute in a parent class. it's giving boundaries βœ‹

πŸ’€ DEPRECATED SETTER πŸ’€

use Test2::Harness::Util::HashBase qw/^foo/;
  • set_foo() β€” this will set the value, but it'll also warn you that the method is deprecated. it works, it's just loud about it.

πŸ“ NO SETTER πŸ“

use Test2::Harness::Util::HashBase qw/<foo/;

only gives you a reader β€” no set_foo method is defined at all. what you see is what you get.

🌸 NO READER 🌸

use Test2::Harness::Util::HashBase qw/>foo/;

only gives you a write (set_foo) β€” no foo method is defined at all.

⭐ CONSTANT ONLY ⭐

use Test2::Harness::Util::HashBase qw/+foo/;

this does not create any methods for you, it just adds the FOO constant. minimal. clean. aesthetic.


πŸŽ€ SUBCLASSING πŸŽ€

you can subclass an existing HashBase class, absolutely.

use base 'Another::HashBase::Class';
use Test2::Harness::Util::HashBase qw/foo bar baz/;

the base class gets added to @ISA for you, and all constants from base classes get added to subclasses automatically. you don't lift a finger. queen behavior πŸ‘‘


πŸ”₯ GETTING A LIST OF ATTRIBUTES FOR A CLASS πŸ”₯

Test2::Harness::Util::HashBase provides a function for retrieving a list of attributes for an Test2::Harness::Util::HashBase class.

@list = Test2::Harness::Util::HashBase::attr_list($class)
@list = $class->Test2::Harness::Util::HashBase::attr_list()

either form above will work. this returns a list of attributes defined on the object. the list comes back in attribute definition order β€” parent class attributes are listed before subclass attributes. duplicate attributes get removed before the list is returned, so no repeats bestie.

Note: this list is used in the $class->new(\@ARRAY) constructor to figure out which attribute each value gets paired with.

πŸ’œ SOURCE πŸ’œ

the source code repository for HashBase lives at http://github.com/Test-More/HashBase/. go look. it's right there.


🌟 MAINTAINERS 🌟

Chad Granum <exodist@cpan.org>


🌟 AUTHORS 🌟

Chad Granum <exodist@cpan.org>


Copyright 2017 Chad Granum <exodist@cpan.org>.

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

See http://dev.perl.org/licenses/


and that's the whole page, bestie πŸ’… this one came out of perl v5.40.1 on 2026-05-10, under the manual name Test2:...shBase(3pm) β€” yes the title got truncated, and yes it's still iconic. User Contributed Perl Documentation, no cap. mwah 🫢✨

πŸ“¦ where this page comes from