NAME

    Object::Pad - a simple syntax for lexical slot-based objects

SYNOPSIS

       use Object::Pad;
    
       class Point {
          has $x = 0;
          has $y = 0;
    
          method BUILD {
            ($x, $y) = @_;
          }
    
          method move ($dX, $dY) {
             $x += $dX;
             $y += $dY;
          }
    
          method describe {
             print "A point at ($x, $y)\n";
          }
       }
    
       Point->new(5,10)->describe;

DESCRIPTION

    WARNING This is an experimental proof-of-concept. Please don't actually
    use this in production unless you are crazy :)

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

 Automatic Construction

    Classes are automatically provided with a constructor method, called
    new, which helps create the object instances.

    By default, this constructor will invoke the BUILD method of every
    component class, passing the list of arguments the constructor was
    invoked with. Each class should perform its required setup behaviour in
    a method called BUILD, but does not need to chain to the SUPER class
    first; this is handled automatically.

       $self->BUILD( @_ )  # for each component class

    If the class provides a BUILDARGS class method, that is used to mangle
    the list of arguments before the BUILD methods 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( @_ )
       $self->BUILD( @args )  # for each component class

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 extends

       class Name extends BASECLASS {
          ...
       }
    
       class Name extends BASECLASS VERSION {
          ...
       }

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

       require Animal ();

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

    The superclass must either be implemented by Object::Pad, or be some
    class whose instances are blessed hash references. For more detail on
    this latter case see "SUBCLASSING CLASSIC PERL CLASSES".

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

       BaseClass->VERSION( $ver )

    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 "slots").

    The following class attributes are supported:

  :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.

 has

       has $var;
       has $var = CONST;
       has @var;
       has %var;

    Declares that the instances of the class have a member field of the
    given name. This member field (called a "slot") 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. They are not visible to users of
    the class, nor to subclasses. In order to provide access to them a
    class may wish to use "method" to create an accessor.

    A scalar slot may provide a expression that gives an initialisation
    value, which will be assigned into the slot of every instance during
    the constructor before the BUILD methods are invoked. For
    ease-of-implementation reasons this expression must currently be a
    compiletime constant, but it is hoped that a future version will relax
    this restriction and allow runtime-computed values.

 method

       method NAME {
          ...
       }
    
       method NAME (SIGNATURE) {
          ...
       }
    
       method NAME :ATTRS... {
          ...
       }

    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
    ("slots") 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.

    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
    slots.

       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.

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.

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 slot initialisers will have been invoked but the BUILD
    methods 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 extends ClassicPerlBaseClass {
          has $_value = "B";
          method 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 method will not have been invoked. The $_value slot will still
    exist, but its value will be B during the superconstructor. After the
    superconstructor, the BUILD methods 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.

 File Layout

    Begin the file with a use Object::Pad line; ideally including a
    minimum-required version. This should be followed by the toplevel class
    declaration 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;
    
       class My::Classname 1.23;
    
       # other use statements
    
       # has, methods, etc.. can go here

 Slot Names

    Slot 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;  method name  :lvalue { $name }
          has $value; method value :lvalue { $value }
       }

    In larger examples with lots of non-trivial method bodies, it can get
    confusing to remember where the slot variables come from (because we no
    longer have the $self->{ ... } visual clue). In these cases it is
    suggested to prefix the slot 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 slot
          }
       }

WITH OTHER MODULES

 Syntax::Keyword::Dynamically

    A cross-module integration test asserts that dynamically works
    correctly on object instance slots:

       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 slots can be dynamically set during a
    suspended async method.

DESIGN TODOs

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

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

      * Consider the visibility of superclass slots to subclasses. Do
      subclasses even need to be able to see their superclass's slots, 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:

      * Implement roles, including required method checking and the ability
      to have private slots.

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

      * Some extensions of the has syntax:

      Non-constant default expressions

         has $var = EXPR;

      A way to request generated accessors - ro or rw.

      * 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 slot 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;
            ...
         }

AUTHOR

    Paul Evans <leonerd@leonerd.org.uk>

