jammy (3) Object::Pad.3pm.gz

Provided by: libobject-pad-perl_0.61-1_amd64 bug

NAME

       "Object::Pad" - a simple syntax for lexical field-based objects

SYNOPSIS

       On perl version 5.26 onwards:

          use v5.26;
          use Object::Pad;

          class Point {
             has $x :param = 0;
             has $y :param = 0;

             method move ($dX, $dY) {
                $x += $dX;
                $y += $dY;
             }

             method describe () {
                print "A point at ($x, $y)\n";
             }
          }

          Point->new(x => 5, y => 10)->describe;

       Or, for older perls that lack signatures:

          use Object::Pad;

          class Point {
             has $x :param = 0;
             has $y :param = 0;

             method move {
                my ($dX, $dY) = @_;
                $x += $dX;
                $y += $dY;
             }

             method describe {
                print "A point at ($x, $y)\n";
             }
          }

          Point->new(x => 5, y => 10)->describe;

DESCRIPTION

       This module provides a simple syntax for creating object classes, which uses private variables that look
       like lexicals as object member fields.

       WARNING This module is still experimental. The parts that currently exist do seem to work reliably but
       much of the design is still evolving, and many features and have yet to be implemented. I don't yet
       guarantee I won't have to change existing details in order to continue its development. Feel free to try
       it out in experimental or newly-developed code, but don't complain if a later version is incompatible
       with your current code and you'll have to change it.

       That all said, please do get in contact if you find the module overall useful.  The more feedback you
       provide in terms of what features you are using, what you find works, and what doesn't, will help the
       ongoing development and hopefully eventual stability of the design. See the "FEEDBACK" section.

   Automatic Construction
       Classes are automatically provided with a constructor method, called "new", which helps create the object
       instances. This may respond to passed arguments, automatically assigning values of fields, and invoking
       other blocks of code provided by the class. It proceeds in the following stages:

       The BUILDARGS phase

       If the class provides a "BUILDARGS" class method, that is used to mangle the list of arguments before the
       "BUILD" blocks are called. Note this must be a class method not an instance method (and so implemented
       using "sub"). It should perform any "SUPER" chaining as may be required.

          @args = $class->BUILDARGS( @_ )

       Field assignment

       If any field in the class has the ":param" attribute, then the constructor will expect to receive its
       argmuents in an even-sized list of name/value pairs. This applies even to fields inherited from the
       parent class or applied roles. It is therefore a good idea to shape the parameters to the constructor in
       this way in roles, and in classes if you intend your class to be extended.

       The constructor will also check for required parameters (these are all the parameters for fields that do
       not have default initialisation expressions). If any of these are missing an exception is thrown.

       The BUILD phase

       As part of the construction process, the "BUILD" block of every component class will be invoked, passing
       in the list of arguments the constructor was invoked with. Each class should perform its required setup
       behaviour, but does not need to chain to the "SUPER" class first; this is handled automatically.

       The ADJUST phase

       Next, the "ADJUST" and "ADJUSTPARAMS" block of every component class is invoked. This happens after the
       fields are assigned their initial values and the "BUILD" blocks have been run.

       Note also that both "ADJUST" and "ADJUSTPARAMS" blocks happen at the same time, in declaration order. The
       "ADJUSTPARAMS" blocks do not form their own separate phase.

       The strict-checking phase

       Finally, before the object is returned, if the ":strict(params)" class attribute is present, then the
       constructor will throw an exception if there are any remaining named arguments left over after assigning
       them to fields as per ":param" declarations, and running any "ADJUSTPARAMS" blocks.

KEYWORDS

   class
          class Name :ATTRS... {
             ...
          }

          class Name :ATTRS...;

       Behaves similarly to the "package" keyword, but provides a package that defines a new class. Such a class
       provides an automatic constructor method called "new".

       As with "package", an optional block may be provided. If so, the contents of that block define the new
       class and the preceding package continues afterwards. If not, it sets the class as the package context of
       following keywords and definitions.

       As with "package", an optional version declaration may be given. If so, this sets the value of the
       package's $VERSION variable.

          class Name VERSION { ... }

          class Name VERSION;

       A single superclass is supported by the keyword "isa"

       Since version 0.41.

          class Name isa BASECLASS {
             ...
          }

          class Name isa BASECLASS BASEVER {
             ...
          }

       Prior to version 0.41 this was called "extends", which is currently recognised as a compatibility
       synonym. Both "extends" and "isa" keywords are now discouraged, in favour of the ":isa" attribute which
       is preferred because it follows a more standard grammar without this special-case.

       One or more roles can be composed into the class by the keyword "does"

       Since version 0.41.

          class Name does ROLE, ROLE,... {
             ...
          }

       Prior to version 0.41 this was called "implements", which is currently recognised as a compatibility
       synonym. Both "implements" and "does" keywords are now discouraged, in favour of the ":does" attribute
       which is preferred because it follows a more standard grammar without this special-case.

       An optional list of attributes may be supplied in similar syntax as for subs or lexical variables. (These
       are annotations about the class itself; the concept should not be confused with per-object-instance data,
       which here is called "fields").

       Whitespace is permitted within the value and is automatically trimmed, but as standard Perl parsing
       rules, no space is permitted between the attribute's name and the open parenthesis of its value:

          :attr( value here )     # is permitted
          :attr (value here)      # not permitted

       The following class attributes are supported:

       :isa

          :isa(CLASS)

          :isa(CLASS CLASSVER)

       Since version 0.57.

       Declares a superclass that this class extends. At most one superclass is supported.

       If the package providing the superclass does not exist, an attempt is made to load it by code equivalent
       to

          require CLASS ();

       and thus it must either already exist, or be locatable via the usual @INC mechanisms.

       The superclass may or may not itself be implemented by "Object::Pad", but if it is not then see
       "SUBCLASSING CLASSIC PERL CLASSES" for further detail on the semantics of how this operates.

       An optional version check can also be supplied; it performs the equivalent of

          BaseClass->VERSION( $ver )

       :does

          :does(ROLE)

          :does(ROLE ROLEVER)

       Since version 0.57.

       Composes a role into the class; optionally requiring a version check on the role package. This is a newer
       form of the "implements" and "does" keywords and should be preferred for new code.

       Multiple roles can be composed by using multiple ":does" attributes, one per role.

       The package will be loaded in a similar way to how the ":isa" attribute is handled.

       :repr(TYPE)

       Sets the representation type for instances of this class. Must be one of the following values:

          :repr(native)

       The native representation. This is an opaque representation type whose contents are not specified. It
       only works for classes whose entire inheritence hierarchy is built only from classes based on
       "Object::Pad".

          :repr(HASH)

       The representation will be a blessed hash reference. The instance data will be stored in an array
       referenced by a key called "Object::Pad/slots", which is fairly unlikely to clash with existing storage
       on the instance. No other keys will be used; they are available for implementions and subclasses to use.
       The exact format of the value stored here is not specified and may change between module versions, though
       it can be relied on to be well-behaved as some kind of perl data structure for purposes of modules like
       Data::Dumper or serialisation into things like "YAML" or "JSON".

       This representation type may be useful when converting existing classes into using "Object::Pad" where
       there may be existing subclasses of it that presume a blessed hash for their own use.

          :repr(magic)

       The representation will use MAGIC to apply the instance data in a way that is invisible at the Perl
       level, and shouldn't get in the way of other things the instance is doing even in XS modules.

       This representation type is the only one that will work for subclassing existing classes that do not use
       blessed hashes.

          :repr(autoselect), :repr(default)

       Since version 0.23.

       This representation will select one of the representations above depending on what is best for the
       situation. Classes not derived from a non-"Object::Pad" base class will pick "native", and classes
       derived from non-"Object::Pad" bases will pick either the "HASH" or "magic" forms depending on whether
       the instance is a blessed hash reference or some other kind.

       This achieves the best combination of DWIM while still allowing the common forms of hash reference to be
       inspected by "Data::Dumper", etc. This is the default representation type, and does not have to be
       specifically requested.

       :strict(params)

       Since version 0.43.

       Can only be applied to classes that contain no "BUILD" blocks. If set, then the constructor will complain
       about any unrecognised named arguments passed to it (i.e. names that do not correspond to the ":param" of
       any defined field and left unconsumed by any "ADJUSTPARAMS" block).

       Since "BUILD" blocks can inspect the arguments arbitrarily, the presence of any such block means the
       constructor cannot determine which named arguments are not recognised.

       This attribute is a temporary stepping-stone for compatibility with existing code. It is recommended to
       enable this whenever possible, as a later version of this module will likely perform this behaviour
       unconditionally whenever no "BUILD" blocks are present.

   role
          role Name :ATTRS... {
             ...
          }

          role Name :ATTRS...;

       Since version 0.32.

       Similar to "class", but provides a package that defines a new role. A role acts simliar to a class in
       some respects, and differently in others.

       Like a class, a role can have a version, and named methods.

          role Name VERSION {
             method a { ... }
             method b { ... }
          }

       A role does not provide a constructor, and instances cannot directly be constructed. A role cannot extend
       a class.

       A role can declare that it requires methods of given names from any class that implements the role.

          role Name {
             requires METHOD;
          }

       A role can provide instance fields. These are visible to any "BUILD" blocks or methods provided by that
       role.

       Since version 0.33.

          role Name {
             has $field;

             BUILD { $field = "a value" }

             method field { return $field }
          }

       Since version 0.57 a role can declare that it provides another role:

          role Name :does(OTHERROLE) { ... }
          role Name :does(OTHERROLE OTHERVER) { ... }

       This will include all of the methods from the included role. Effectively this means that applying the
       "outer" role to a class will imply applying the other role as well.

       The following role attributes are supported:

       :compat(invokable)

       Since version 0.35.

       Enables a form of backward-compatibility behaviour useful for gradually upgrading existing code from
       classical Perl inheritance or mixins into using roles.

       Normally, methods of a role cannot be directly invoked and the role must be applied to an
       Object::Pad-based class in order to be used. This however presents a problem when gradually upgrading
       existing code that already uses techniques like roles, multiple inheritance or mixins when that code may
       be split across multiple distributions, or for some other reason cannot be upgraded all at once. Methods
       within a role that has the ":compat(invokable)" attribute applied to it may be directly invoked on any
       object instance. This allows the creation of a role that can still provide code for existing classes
       written in classical Perl that has not yet been rewritten to use "Object::Pad".

       The tradeoff is that a ":compat(invokable)" role may not create field data using the "has" keyword.
       Whatever behaviours the role wishes to perform must be provided only by calling other methods on $self,
       or perhaps by making assumptions about the representation type of instances.

       It should be stressed again: This option is only intended for gradual upgrade of existing classical Perl
       code into using "Object::Pad". When all existing code is using "Object::Pad" then this attribute can be
       removed from the role.

   has
          has $var;
          has @var;
          has %var;

          has $var :ATTR ATTR...;

          has $var = EXPR;

          has $var { BLOCK };

       Declares that the instances of the class or role have a member field of the given name. This member field
       will be accessible as a lexical variable within any "method" declarations in the class.

       Array and hash members are permitted and behave as expected; you do not need to store references to
       anonymous arrays or hashes.

       Member fields are private to a class or role. They are not visible to users of the class, nor inherited
       by subclasses nor any class that a role is applied to. In order to provide access to them a class may
       wish to use "method" to create an accessor, or use the attributes such as ":reader" to get one generated.

       A scalar field may provide a expression that gives an initialisation value, which will be assigned into
       the field of every instance during the constructor before the "BUILD" blocks are invoked. Since version
       0.29 this expression does not have to be a compiletime constant, though it is evaluated exactly once, at
       runtime, after the class definition has been parsed. It is not evaluated individually for every object
       instance of that class. Since version 0.54 this is also permitted on array and hash fields.

       Field Initialiser Blocks

       Since version 0.54 a deferred statement block is also permitted, on any field variable type. This is an
       experimental feature that permits code to be executed as part of the instance constructor, rather than
       running just once when the class is set up. Code in a field initialisation block is roughly equivalent to
       being placed in a "BUILD" or "ADJUST" block.

       Control flow that attempts to leave a field initialiser block is not permitted. This includes any
       "return" expression, any "next/last/redo" outside of a loop, with a dynamically-calculated label
       expression, or with a label that it doesn't appear in. "goto" statements are also currently forbidden,
       though known-safe ones may be permitted in future.

       Loop control expressions that are known at compiletime to affect a loop that they appear within are
       permitted.

          has $field { foreach(@list) { next; } }       # this is fine

          has $field { LOOP: while(1) { last LOOP; } }  # this is fine too

       The following field attributes are supported:

       :reader, :reader(NAME)

       Since version 0.27.

       Generates a reader method to return the current value of the field. If no name is given, the name of the
       field is used. A single prefix character "_" will be removed if present.

          has $field :reader;

          # equivalent to
          has $field;  method field { return $field }

       Since version 0.55 these are permitted on any field type, but prior versions only allowed them on scalar
       fields. The reader method behaves identically to how a lexical variable would behave in the same context;
       namely returning a list of values from an array or key/value pairs from a hash when in list context, or
       the number of items or keys when in scalar context.

          has @items :reader;

          foreach my $item ( $obj->items ) { ... }   # iterates the list of items

          my $count = $obj->items;                   # yields count of items

       :writer, :writer(NAME)

       Since version 0.27.

       Generates a writer method to set a new value of the field from its arguments.  If no name is given, the
       name of the field is used prefixed by "set_". A single prefix character "_" will be removed if present.

          has $field :writer;

          # equivalent to
          has $field;  method set_field { $field = shift; return $self }

       Since version 0.28 a generated writer method will return the object invocant itself, allowing a chaining
       style.

          $obj->set_x("x")
             ->set_y("y")
             ->set_z("z");

       Since version 0.55 these are permitted on any field type, but prior versions only allowed them on scalar
       fields. On arrays or hashes, the writer method takes a list of values to be assigned into the field,
       completely replacing any values previously there.

       :mutator, :mutator(NAME)

       Since version 0.27.

       Generates an lvalue mutator method to return or set the value of the field.  These are only permitted for
       scalar fields. If no name is given, the name of the field is used. A single prefix character "_" will be
       removed if present.

          has $field :mutator;

          # equivalent to
          has $field;  method field :lvalue { $field }

       Since version 0.28 all of these generated accessor methods will include argument checking similar to that
       used by subroutine signatures, to ensure the correct number of arguments are passed - usually zero, but
       exactly one in the case of a ":writer" method.

       :accessor, :accessor(NAME)

       Since version 0.53.

       Generates a combined reader-writer accessor method to set or return the value of the field. These are
       only permitted for scalar fields. If no name is given, the name of the field is used. A prefix character
       "_" will be removed if present.

       This method takes either zero or one additional arguments. If an argument is passed, the value of the
       field is set from this argument (even if it is "undef"). If no argument is passed (i.e. "scalar @_" is
       false) then the field is not modified. In either case, the value of the field is then returned.

          has $field :accessor;

          # equivalent to
          has $field;

          method field {
             $field = shift if @_;
             return $field;
          }

       :weak

       Since version 0.44.

       Generated code which sets the value of this field will weaken it if it contains a reference. This applies
       to within the constructor if ":param" is given, and to a ":writer" accessor method. Note that this only
       applies to automatically generated code; not normal code written in regular method bodies. If you assign
       into the field variable you must remember to call "Scalar::Util::weaken" yourself.

       :param, :param(NAME)

       Since version 0.41.

       Sets this field to be initialised automatically in the generated constructor.  This is only permitted on
       scalar fields. If no name is given, the name of the field is used. A single prefix character "_" will be
       removed if present.

       Any field that has ":param" but does not have a default initialisation expression or block becomes a
       required argument to the constructor. Attempting to invoke the constructor without a named argument for
       this will throw an exception. In order to make a parameter optional, make sure to give it a default
       expression - even if that expression is "undef":

          has $x :param;          # this is required
          has $z :param = undef;  # this is optional

       Any field that has a ":param" and an initialisation block will only run the code in the block if required
       by the constructor. If a named parameter is passed to the constructor for this field, then its code block
       will not be executed.

       Values for fields are assigned by the constructor before any "BUILD" blocks are invoked.

   method
          method NAME {
             ...
          }

          method NAME (SIGNATURE) {
             ...
          }

          method NAME :ATTRS... {
             ...
          }

          method NAME;

       Declares a new named method. This behaves similarly to the "sub" keyword, except that within the body of
       the method all of the member fields are also accessible. In addition, the method body will have a lexical
       called $self which contains the invocant object directly; it will already have been shifted from the @_
       array.

       If the method has no body and is given simply as a name, this declares a required method for a role. Such
       a method must be provided by any class that implements the role. It will be a compiletime error to
       combine the role with a class that does not provide this.

       The "signatures" feature is automatically enabled for method declarations. In this case the signature
       does not have to account for the invocant instance; that is handled directly.

          method m ($one, $two) {
             say "$self invokes method on one=$one two=$two";
          }

          ...
          $obj->m(1, 2);

       A list of attributes may be supplied as for "sub". The most useful of these is ":lvalue", allowing easy
       creation of read-write accessors for fields (but see also the ":reader", ":writer" and ":mutator" field
       attributes).

          class Counter {
             has $count;

             method count :lvalue { $count }
          }

          my $c = Counter->new;
          $c->count++;

       Every method automatically gets the ":method" attribute applied, which suppresses warnings about
       ambiguous calls resolved to core functions if the name of a method matches a core function.

       The following additional attributes are recognised by "Object::Pad" directly:

       :override

       Since version 0.29.

       Marks that this method expects to override another of the same name from a superclass. It is an error at
       compiletime if the superclass does not provide such a method.

   method (lexical)
          method $var { ... }

          method $var :ATTRS... (SIGNATURE) { ... }

       Since version 0.59.

       Declares a new lexical method. Lexical methods are not visible via the package namespace, but instead are
       stored directly in a lexical variable (with the same scoping rules as regular "my" variables). These can
       be invoked by subsequent method code in the same block by using "$self->$var(...)"  method call syntax.

          class WithPrivate {
             has $var;

             # Lexical methods can still see instance fields as normal
             method $inc_var { $var++; say "Var was incremented"; }
             method $dec_var { $var--; say "Var was decremented"; }

             method bump {
                $self->$inc_var;
                say "In the middle";
                $self->$dec_var;
             }
          }

          my $obj = WithPrivate->new;

          $obj->bump;

          # Neither $inc_var nor $dec_var are visible here

       This effectively provides the ability to define private methods, as they are inaccessible from outside
       the block that defines the class. In addition, there is no chance of a name collision because lexical
       variables in different scopes are independent, even if they share the same name. This is particularly
       useful in roles, to create internal helper methods without letting those methods be visible to callers,
       or risking their names colliding with other named methods defined on the consuming class.

   BUILD
          BUILD {
             ...
          }

          BUILD (SIGNATURE) {
             ...
          }

       Since version 0.27.

       Declares the builder block for this component class. A builder block may use subroutine signature syntax,
       as for methods, to assist in unpacking its arguments. A build block is not a subroutine and thus is not
       permitted to use subroutine attributes (for example ":lvalue").

       Note that a "BUILD" block is a named phaser block and not a method. Attempts to create a method named
       "BUILD" (i.e. with syntax "method BUILD {...}") will fail with a compiletime error, to avoid this
       confusion.

   ADJUST
          ADJUST {
             ...
          }

       Since version 0.43.

       Declares an adjust block for this component class. This block of code runs within the constructor, after
       any "BUILD" blocks and automatic field value assignment. It can make any final adjustments to the
       instance (such as initialising fields from calculated values). No additional parameters are passed.

       An adjust block is not a subroutine and thus is not permitted to use subroutine attributes. Note that an
       "ADJUST" block is a named phaser block and not a method; it does not use the "sub" or "method" keyword.

   ADJUSTPARAMS
          ADJUSTPARAMS ( $params ) {    # on perl 5.26 onwards
             ...
          }

          ADJUSTPARAMS {
             my $params = shift;
             ...
          }

       Since version 0.51.

       Declares an adjust block for this component class that receives the parameters hash reference. This block
       of code runs within the constructor at the same time as "ADJUST" blocks, but receives in addition a
       reference to the hash containing the current constructor parameters. This hash will not contain any
       constructor parameters already consumed by ":param" declarations on any fields, but only the leftovers
       once those are processed.

       The code in the block should "delete" from this hash any parameters it wishes to consume. Once all the
       "ADJUSTPARAMS" blocks have run, any remaining keys in the hash will be considered errors, subject to the
       ":strict(params)" check.

   requires
          requires NAME;

       Declares that this role requires a method of the given name from any class that implements it. It is an
       error at compiletime if the implementing class does not provide such a method.

       This form of declaring a required method is now vaguely discouraged, in favour of the bodyless "method"
       form described above.

CREPT FEATURES

       While not strictly part of being an object system, this module has nevertheless gained a number of
       behaviours by feature creep, as they have been found useful.

   Implied Pragmata
       In order to encourage users to write clean, modern code, the body of the "class" block acts as if the
       following pragmata are in effect:

          use strict;
          use warnings;
          no indirect ':fatal';  # or  no feature 'indirect' on perl 5.32 onwards
          use feature 'signatures';

       This list may be extended in subsequent versions to add further restrictions and should not be considered
       exhaustive.

       Further additions will only be ones that remove "discouraged" or deprecated language features with the
       overall goal of enforcing a more clean modern style within the body. As long as you write code that is in
       a clean, modern style (and I fully accept that this wording is vague and subjective) you should not find
       any new restrictions to be majorly problematic. Either the code will continue to run unaffected, or you
       may have to make some small alterations to bring it into a conforming style.

   Yield True
       A "class" statement or block will yield a true boolean value. This means that it can be used directly
       inside a .pm file, avoiding the need to explicitly yield a true value from the end of it.

SUBCLASSING CLASSIC PERL CLASSES

       There are a number of details specific to the case of deriving an "Object::Pad" class from an existing
       classic Perl class that is not implemented using "Object::Pad".

   Storage of Instance Data
       Instances will pick either the ":repr(HASH)" or ":repr(magic)" storage type.

   Object State During Methods Invoked By Superclass Constructor
       It is common in classic Perl OO style to invoke methods on $self during the constructor. This is
       supported here since "Object::Pad" version 0.19.  Note however that any methods invoked by the superclass
       constructor may not see the object in a fully consistent state. (This fact is not specific to using
       "Object::Pad" and would happen in classic Perl OO as well). The field initialisers will have been invoked
       but the "BUILD" blocks will not.

       For example; in the following

          package ClassicPerlBaseClass {
             sub new {
                my $self = bless {}, shift;
                say "Value seen by superconstructor is ", $self->get_value;
                return $self;
             }
             sub get_value { return "A" }
          }

          class DerivedClass :isa(ClassicPerlBaseClass) {
             has $_value = "B";
             BUILD {
                $_value = "C";
             }
             method get_value { return $_value }
          }

          my $obj = DerivedClass->new;
          say "Value seen by user is ", $obj->get_value;

       Until the "ClassicPerlBaseClass::new" superconstructor has returned the "BUILD" block will not have been
       invoked. The $_value field will still exist, but its value will be "B" during the superconstructor. After
       the superconstructor, the "BUILD" blocks are invoked before the completed object is returned to the user.
       The result will therefore be:

          Value seen by superconstructor is B
          Value seen by user is C

STYLE SUGGESTIONS

       While in no way required, the following suggestions of code style should be noted in order to establish a
       set of best practices, and encourage consistency of code which uses this module.

   $VERSION declaration
       While it would be nice for CPAN and other toolchain modules to parse the embedded version declarations in
       "class" statements, the current state at time of writing (June 2020) is that none of them actually do. As
       such, it will still be necessary to make a once-per-file $VERSION declaration in syntax those modules can
       parse.

       Further note that these modules will also not parse the "class" declaration, so you will have to
       duplicate this with a "package" declaration as well as a "class" keyword. This does involve repeating the
       package name, so is slightly undesirable.

       It is hoped that eventually upstream toolchain modules will be adapted to accept the "class" syntax as
       being sufficient to declare a package and set its version.

       See also

       • <https://github.com/Perl-Toolchain-Gang/Module-Metadata/issues/33>

   File Layout
       Begin the file with a "use Object::Pad" line; ideally including a minimum-required version. This should
       be followed by the toplevel "package" and "class" declarations for the file. As it is at toplevel there
       is no need to use the block notation; it can be a unit class.

       There is no need to "use strict" or apply other usual pragmata; these will be implied by the "class"
       keyword.

          use Object::Pad 0.16;

          package My::Classname 1.23;
          class My::Classname;

          # other use statements

          # has, methods, etc.. can go here

   Field Names
       Field names should follow similar rules to regular lexical variables in code - lowercase, name components
       separated by underscores. For tiny examples such as "dumb record" structures this may be sufficient.

          class Tag {
             has $name  :mutator;
             has $value :mutator;
          }

       In larger examples with lots of non-trivial method bodies, it can get confusing to remember where the
       field variables come from (because we no longer have the "$self->{ ... }" visual clue). In these cases it
       is suggested to prefix the field names with a leading underscore, to make them more visually distinct.

          class Spudger {
             has $_grapefruit;

             ...

             method mangle {
                $_grapefruit->peel; # The leading underscore reminds us this is a field
             }
          }

WITH OTHER MODULES

   Syntax::Keyword::Dynamically
       A cross-module integration test asserts that "dynamically" works correctly on object instance fields:

          use Object::Pad;
          use Syntax::Keyword::Dynamically;

          class Container {
             has $value = 1;

             method example {
                dynamically $value = 2;
                ,..
                # value is restored to 1 on return from this method
             }
          }

   Future::AsyncAwait
       As of Future::AsyncAwait version 0.38 and Object::Pad version 0.15, both modules now use
       XS::Parse::Sublike to parse blocks of code. Because of this the two modules can operate together and
       allow class methods to be written as async subs which await expressions:

          use Future::AsyncAwait;
          use Object::Pad;

          class Example
          {
             async method perform ($block)
             {
                say "$self is performing code";
                await $block->();
                say "code finished";
             }
          }

       These three modules combine; there is additionally a cross-module test to ensure that object instance
       fields can be "dynamically" set during a suspended "async method".

DESIGN TODOs

       The following points are details about the design of pad field-based object systems in general:

       •   Is multiple inheritence actually required, if role composition is implemented including giving roles
           the ability to use private fields?

       •   Consider the visibility of superclass fields to subclasses. Do subclasses even need to be able to see
           their superclass's fields, or are accessor methods always appropriate?

           Concrete example: The "$self->{split_at}" access that Tickit::Widget::HSplit makes of its parent
           class Tickit::Widget::LinearSplit.

IMPLEMENTATION TODOs

       These points are more about this particular module's implementation:

       •   Consider multiple inheritence of subclassing, if that is still considered useful after adding roles.

       •   Work out why "no indirect" doesn't appear to work properly before perl 5.20.

       •   Work out why we don't get a "Subroutine new redefined at ..." warning if we

             sub new { ... }

       •   The "local" modifier does not work on field variables, because they appear to be regular lexicals to
           the parser at that point. A workaround is to use Syntax::Keyword::Dynamically instead:

              use Syntax::Keyword::Dynamically;

              has $loglevel;

              method quietly {
                 dynamically $loglevel = LOG_ERROR;
                 ...
              }

FEEDBACK

       The following resources are useful forms of providing feedback, especially in the form of reports of what
       you find good or bad about the module, requests for new features, questions on best practice, etc...

       •   The RT queue at <https://rt.cpan.org/Dist/Display.html?Name=Object-Pad>.

       •   The "#cor" IRC channel on "irc.perl.org".

SPONSORS

       With thanks to the following sponsors, who have helped me be able to spend time working on this module
       and other perl features.

       •   Oetiker+Partner AG <https://www.oetiker.ch/en/>

       •   Deriv <http://deriv.com>

       •   Perl-Verein Schweiz <https://www.perl-workshop.ch/>

       Additional details may be found at <https://github.com/Ovid/Cor/wiki/Sponsors>.

AUTHOR

       Paul Evans <leonerd@leonerd.org.uk>