class#
Declare a namespace that behaves as a native object class.
class introduces a new package just like package, but
marks it as a class: the runtime attaches a constructor named new,
enables the field and method keywords inside its
body, and supports single inheritance through the :isa attribute.
It is the core-language answer to hand-rolled bless-based
OO — the same problem, without the boilerplate.
Note
Experimental
The class feature (codename Corinna) is experimental in Perl 5.42
and may still change in incompatible ways. Enable it with
use feature 'class' and silence the notice with
no warnings 'experimental::class'.
Synopsis#
class NAMESPACE; # rest-of-scope form
class NAMESPACE VERSION;
class NAMESPACE :ATTRIBUTES;
class NAMESPACE BLOCK # block form
class NAMESPACE VERSION BLOCK
class NAMESPACE VERSION :ATTRIBUTES BLOCK
Minimal working class:
use v5.38;
use feature 'class';
no warnings 'experimental::class';
class Point {
field $x :param;
field $y :param;
method distance_from_origin {
return sqrt($x ** 2 + $y ** 2);
}
}
my $p = Point->new(x => 3, y => 4);
say $p->distance_from_origin; # 5
What you get back#
class is a declaration, not an expression — it does not return a
value you can assign. What you get is:
A new package in the symbol table, reachable as any other package.
A generated
newconstructor. Do not write your ownnew. The generated one honours:paramfield attributes and runs everyADJUSTblock in declaration order.$selfimplicitly bound inside everymethodbody.__CLASS__usable inside field initialisers and methods to name the class currently being constructed (which may be a subclass).
Forms#
class accepts four syntactic shapes. The split between block
and statement forms mirrors package exactly:
class NAME BLOCK— the class definition is the contents of the block. Scope ends with the closing brace.class NAME;— the rest of the current scope (or file) up to the nextclassorpackagestatement is the class body. Useful for single-class files.class NAME VERSION ...— the version is declared likepackage Foo 1.234. The version must precede any attributes.class NAME :ATTRIBUTES ...— one or more class attributes, separated by whitespace, each starting with:. The only currently defined class attribute is:isa.
class My::Thing 1.02 :isa(My::Base) {
# body
}
Fields, methods, ADJUST#
Inside a class body three new keywords are in scope:
fielddeclares per-instance storage. Fields behave like lexicals inside methods but each instance has its own slot. Attributes:param,:reader, and:writergenerate constructor binding and accessors.methoddeclares a subroutine that auto-binds$selfand that can read and write the enclosing fields by name. Methods act as ifuse feature 'signatures'were in effect;$selfdoes not appear in the signature.ADJUST BLOCKruns after field initialisers, during construction, with$selfalready bound. Use it for post-construction validation and for derived fields.
class Counter {
field $value :param = 0;
field $step :param = 1;
ADJUST {
die "step must be positive" if $step <= 0;
}
method tick { $value += $step }
method peek { $value }
}
Fields are always lexical to the class — they are not inherited. Subclasses that need access to a parent’s state do so through methods, not through fields.
Inheritance: :isa#
A class inherits from at most one other class:
class Shape { ... }
class Circle :isa(Shape) {
field $r :param;
method area { 3.14159265 * $r * $r }
}
Only single inheritance is supported. The :isa target is loaded
automatically if it is not already in memory — equivalent to
use MODULE () before the class declaration. A minimum version can
be required the same way use MODULE VERSION does:
class Circle :isa(Shape 2.000) { ... }
:isa only inherits methods. Fields are per-class private
storage; a subclass has no implicit view into a parent’s fields.
Global state it touches#
%INC—:isa(Parent)loadsParentviarequireon first use and records it here, just likeuse.@ISA— populated for the class from the:isaattribute, so existingisa/UNIVERSAL/SUPER::introspection keeps working.The symbol table — the class name becomes a stash in
%::exactly aspackagewould create one.
Examples#
Plain class with a required parameter and a derived field:
class User {
field $name :param;
field $greeting;
ADJUST { $greeting = "Hello, $name" }
method greet { say $greeting }
}
User->new(name => 'Ada')->greet; # Hello, Ada
Default parameter values — = applies when the caller omitted the
parameter; //= also applies when the value was undef; ||= also
applies when the value was false:
class Window {
field $title :param = 'untitled';
field $width :param //= 640;
field $shown :param ||= 1;
}
Single inheritance with a method override:
class Animal {
field $name :param;
method speak { "some sound" }
method introduce { say $name, " says ", $self->speak }
}
class Dog :isa(Animal) {
method speak { "woof" }
}
Dog->new(name => 'Rex')->introduce; # Rex says woof
Private method via lexical my method, invoked through ->&:
class Safe {
field $secret :param;
my method check ($n) { $n == $secret }
method unlock ($n) {
return $self->&check($n) ? "open" : "denied";
}
}
Using __CLASS__ so a base-class field initialiser picks up the
subclass’s override:
class Base {
sub DEFAULT_X { 10 }
field $x = __CLASS__->DEFAULT_X;
method x { $x }
}
class Tuned :isa(Base) {
sub DEFAULT_X { 99 }
}
say Tuned->new->x; # 99
Rest-of-file statement form:
use v5.38;
use feature 'class';
class Config;
field $path :param;
method path { $path }
# File ends here; whole remainder is Config's body.
Edge cases#
Do not define
new. The generated constructor is the only supported entry point. A user-writtensub new { ... }inside aclassbody is a compile-time error.No multiple inheritance.
:isa(A, B)is a syntax error. Multiple:isaattributes on one class are also rejected.No
@ISAmanipulation. Treat@ISAas read-only for classes declared withclass. Pushing onto it at runtime is undefined.packagecannot re-open a class. Once a namespace has been declared withclass, subsequentpackagestatements targeting the same name are a compile-time error, and vice versa.Fields are not lexicals in the usual sense. You cannot refer to a field from outside the class body, and you cannot
ourorlocalit. Only methods andADJUSTblocks see fields.$selfis read-only inside a method. Assigning to it is a runtime error.Field initialisers run before
$selfexists. Insidefield $x = EXPR, you can use__CLASS__and previously declared fields, but not$self. Anything that needs the fully built instance belongs in anADJUSTblock.No field access before declaration. Within a field’s initialiser expression, only fields declared earlier in the class body are visible.
Method resolution. Dispatch still goes through the usual MRO (
UNIVERSAL::isa,SUPER::), so$self->SUPER::foo(@args)works the way it does forbless-based classes.Statement form scope.
class Foo;consumes the rest of the enclosing block — typically the rest of the file. A secondclassorpackageterminates it; there is no way to “close” a statement-form class early.Experimental warning. Every
classdeclaration emits aclass is experimentalwarning under the default warnings. Useno warnings 'experimental::class'once the feature is in use for real.
Differences from upstream#
Fully compatible with upstream Perl 5.42. The feature is flagged
experimental in upstream; pperl mirrors that status and emits the
same warning category (experimental::class).
See also#
field— declares per-instance storage within aclassbody; supports:param,:reader,:writermethod— declares a subroutine with implicit$selfand direct access to the enclosing class’s fieldspackage— the non-class namespace declaration;classis the OO-aware sibling with the same syntactic formsbless— the pre-5.38 way to attach a class to a reference; still supported, and interoperates withclass-built objects forisa/canchecksisa— operator for testing class membership; works for bothclass-declared andbless-based objectsuse— how:isa(Parent)loads the parent class under the hood