Perl's experimental classes give fields their own storage
Perl 5.37.9 introduces native class syntax with private fields and generated constructors. The implementation changes object storage as well as the spelling of methods.
Perl's original object model lets a program bless a reference into a package and dispatch methods through that package. The flexibility leaves much of an object's structure to convention. The new experimental class implementation gives the interpreter direct knowledge of instance fields and methods. Its documentation explicitly describes a new interpreter facility, rather than a wrapper around bless.
The Perl release history records Perl 5.37.9 on February 20. Its release notes introduce class, with per-instance fields that behave like lexical variables. The accompanying class reference, written by Paul Evans and Bartosz Jarzyna, explains the storage and construction rules in enough detail to distinguish the implementation from familiar package-based objects.
I value Perl most for direct text work, so a new object system is not automatically a reason to change how I write a short script. The interesting part is what the interpreter can guarantee once it understands a field declaration. That can reduce the amount of object behavior a reader must reconstruct from conventions.
A field belongs to an instance
A field declaration resembles a lexical declaration, but each instance receives separate storage. Methods refer to the field by its variable name. The field remains private to the declaring class, and an explicit accessor can expose it to callers. That makes field visibility part of the language's scope rules.
This example uses the syntax documented in this development release:
use v5.36;
use feature 'class';
no warnings 'experimental::class';
class Counter {
field $count = 0;
method increment {
return ++$count;
}
}
my $a = Counter->new;
my $b = Counter->new;
say $a->increment;
say $a->increment;
say $b->increment;
The expected values are 1, 2, and 1. The declaration of $count is shared source text, while its value belongs to the receiver. Initialization happens during construction of each instance. A normal lexical variable declared outside that field declaration would have its normal lexical lifetime instead.
Fields can also be arrays or hashes. Their initializing expressions run for each object, and those expressions can read previously initialized fields. The reference illustrates this with a lexical sequence counter used to assign a different initial field value to each object. The distinction between shared lexical state and instance state remains visible in the declarations.
Constructors have a defined interface
Declaring a class supplies a constructor named new. The reference tells class authors not to write their own constructor. A scalar field marked :param obtains its value from a named constructor argument. Without a default expression, that parameter is required and its absence raises an exception.
The parameter name normally matches the field name without its sigil. An attribute argument can supply a different public name. This separates the constructor's interface from the internal variable spelling without requiring a hand-written argument parser.
Default expressions distinguish missing arguments from other values. With =, the default applies when the caller omits the parameter. The documented //= form also substitutes for an undefined value, while ||= substitutes for a false value. Those differences matter for fields where zero or an empty string is meaningful. A constructor can express its intended acceptance rule at the field declaration.
ADJUST blocks run user code during construction, in declaration order. They can access $self and fields created up to that point. That supplies a place for construction logic while retaining the generated constructor. The reference lists parameters to ADJUST blocks among unfinished work, so the available initialization mechanism should not be confused with that proposed extension.
Method arguments exclude the receiver
A method declaration supplies a lexical $self automatically. Its signature describes the explicit arguments, with the receiver excluded from that list. Methods act as though the signatures feature is enabled. This removes the repeated argument handling that a package subroutine otherwise needs to establish its receiver.
The implementation also supports anonymous methods. Their existence matters because method behavior is not restricted to declarations with permanent names. However, the field scope still comes from the class containing the declaration. Calling something a method does not grant it access to another class's private fields.
Inheritance uses the class attribute :isa, with one superclass. Inherited methods are available, but inherited fields remain inaccessible by name because those fields are lexical to their declaring class. A subclass therefore uses the parent's methods to operate on the parent's state. The implementation makes that privacy rule hold across inheritance as well as ordinary calls.
I find this separation useful because method reuse and direct access to representation often get treated as one decision. Here the documented inheritance mechanism reuses behavior without opening the parent's field scope. That makes the boundary a property of the declaration rather than an agreement between authors.
The experiment is deliberately incomplete
The release emits warnings in the experimental::class category. Suppressing that category acknowledges the experiment and removes its warnings. It does not change the documented expectation that later development may add, refine, or alter the implementation.
The class reference identifies roles and generated accessor attributes as unfinished work. Its metaprogramming and extension-customization sections also describe capabilities still to be added. Examples in that TODO section describe possible future syntax, not facilities supplied by this release. A class using an explicit accessor method is within the documented implementation. A declaration using a proposed reader attribute is not justified by this version's TODO example.
These limits affect library design because an experimental language facility can become part of a module's public requirements. Perl 5.37.9 supplies native fields, generated construction, and methods now, while leaving other object-system facilities under development. The concrete change is that the interpreter can represent an instance's private state directly and enforce the scope through which methods access it.