The London Perl and Raku Workshop takes place on 26th Oct 2024. If your company depends on Perl, please consider sponsoring and/or attending.

NAME

OP::Object - Abstract object class

DESCRIPTION

Base abstract object class for the OP framework. Extends OP::Class with a constructor, getters, and setters.

See OP::Array, OP::Hash, OP::Example for concrete implementations.

INHERITANCE

This class inherits additional class and object methods from the following packages:

OP::Class > OP::Object

PUBLIC CLASS METHODS

  • $class->new()

    Returns a new object instance. Optionally accepts a hash or hash ref for use as a prototype object.

      #
      # File: Example.pm
      #
      # Implement a concrete class based on OP::Object:
      #
      use OP::Class;
    
      create "OP::Example" => {
        __BASE__ => "OP::Object"
      };

    Meanwhile, in caller:

      #!/bin/env perl
    
      #
      # File: somecaller.pl
      #
      # New empty object:
      #
      my $obj = OP::Example->new();
    
      #
      # New object from an even list:
      #
      my $objFromList = OP::Example->new(
        foo => "whiskey",
        bar => "tango"
      );
    
      #
      # New object from HASH ref:
      #
      my $objFromRef = OP::Example->new( {
        foo => "whiskey",
        bar => "tango"
      } );
  • $class->proto()

    Constructor method. Returns a new instance of self, populated with default values. The returned object may contain undefined values which must be populated before calling save().

  • $class->attributes()

    Returns a flat list of allowed attributes, if any, for objects of this class. Includes any attribute names in __baseAsserts().

      my @keys = $class->attributes();
  • $class->isAttributeAllowed($key)

    Returns true if the received key is a valid attribute for instances of the current class, otherwise warns to STDERR and returns false.

      #
      # File: Example.pm
      #
      # Create a new class with two attrs, "foo" and "bar"
      #
      my $class = "OP::Example";
    
      create $class => {
        foo => OP::Str->assert(),
    
        bar => OP::Int->assert(),
    
        # ...
      };

    Meanwhile, in caller...

      #!/bin/env perl
    
      #
      # File: somecaller.pl
      #
      # Check for allowed attributes:
      #
      for ( qw| foo bar rebar | ) {
        next if !$class->isAttributeAllowed($_);
    
        # ...
      }
    
      #
      # Expected output is warning text to the effect of:
      #
      # BUG IN CALLER: "rebar" is not a member of class "OP::Example"
      #
  • $class->asserts()

    Abstract method, implemented by subclasses to returns an OP::Hash of assertion objects, including any base assertions which may be present.

      my $asserts = $class->asserts();
  • $class->assert()

    Abstract method, implemented by subclasses to return an assertion object.

    Returns a pre-made OP::Type object with subtypes for the named datatype. See "Concrete Classes" in OP for a list of types which may be asserted.

      create "OP::Example" => {
        someStr     => OP::Str->assert(
          ::optional(),
          ::default("Foo Bar!")
        ),
    
        someInt     => OP::Int->assert( ::optional() ),
        someFloat   => OP::Float->assert( ::optional() ),
        someDouble  => OP::Double->assert( ::optional() ),
        someBool    => OP::Bool->assert( ::default(false) ),
    
        # ...
      };

    To enforce a range of allowed values, use the desired values as arguments:

      create "OP::Example" => {
        foo => OP::Str->assert(qw| alpha bravo cthulhu |);
    
        ...
      };

    If the range of allowed values should be looked up from some external source at runtime (rather than load time), provide an anonymous function (Perl sub{} block or CODE ref).

    This lets the range of allowed values change through the lifetime of the application process, based on whatever the function returns (as opposed to using a static list, which is loaded at "use" time and doesn't adapt to changing data.)

    The function provided should return an unreferenced array of allowed values.

     ...
    
      create "OP::Example" => {
        #
        # Always check against a live datasource:
        #
        someId => OP::Str->assert( sub { OP::Example->allIds() } ),
    
        ...
      };

    Instance variables containing complex data structures, objects, or pointers to external objects follow the same basic form as simple assertions.

    The values for OP::Array and OP::Hash attributes are stored in linked tables, which OP creates and manages.

    OP::ExtID, which is a simple pointer to an external object, is generally a more maintainable approach than inline OP::Array and OP::Hash elements, and also provides the best performance.

PRIVATE CLASS METHODS

Class Callback Methods

  • $class->import()

    Callback method invoked when callers use this package. Provides caller with Types and Bools.

  • $class->__baseAsserts()

    Abstract method.

    Asserts are not inherited by subclasses, unless defined in the hash returned by this method. Override in subclass to provide a hash of inherited assertions.

    Unless implementing a new abstract class that uses special keys, __baseAsserts() does not need to be used or modified. Concrete classes should just use inline assertions as per the examples in OP::Type.

    __baseAsserts() may be overridden as a sub{} or as a class variable.

    Using a sub{} lets you extend the parent class's base asserts, or use any other Perl operation to derive the appropriate values:

      create "OP::Example" => {
        #
        # Inherit parent class's base asserts, tack on "foo"
        #
        __baseAsserts => sub {
          my $class = shift;
    
          my $base = $class->SUPER::__baseAsserts();
    
          $base->{foo} = OP::Str->assert();
    
          return $base;
        },
    
        # ...
      };

    One may alternately use a class variable to redefine base asserts, overriding the parent:

      create "OP::Example" => {
        #
        # Statically assert two base attributes, "id" and "name"
        #
        __baseAsserts => {
          id   => OP::Int->assert(),
    
          name => OP::Str->assert()
        },
    
        # ...
      }

    To inherit no base assertions:

      create "OP::RebelExample" => {
        #
        # Sometimes, parent doesn't know best:
        #
        __baseAsserts => { },
    
        # ...
      }

PUBLIC INSTANCE METHODS

  • $self->get($key)

    Get the received instance variable. Very strict about input enforcement.

    If using assertions, OP *DIES* if the key is invalid!

  • $self->set($key, $value)

    Set the received instance variable. Very strict about input enforcement.

    If using assertions, OP *DIES* on purpose here if key or value are invalid.

  • $self->clear()

    Removes all items, leaving self with zero elements.

      my $object = OP::Example->new(
        foo => "uno",
        bar => "dos"
      );
    
      print $object->size(); # 2
      print "\n";
    
      $object->clear();
    
      print $object->size(); # 0
      print "\n";
  • $self->class()

    Object wrapper for Perl's built-in ref() function

  • $self->value()

    Returns self's value as a native data type, ie dereferences it

AUTOLOADED

  • $self->set<Attribute>($value)

    AUTOLOADed setter method. Set the attribute named in the message to the received value. Does lcfirst on the attribute name.

    Performs value checking and sanitizing (a good reason to use the setter!)

      $self->setFoo("bario")
  • $self-><Attribute>()

    AUTOLOADed getter method. Returns the value for the received attribute.

      $self->setFoo("bario");
    
      my $value = $self->foo(); # returns "bario"
  • $self->delete<Attribute>()

    AUTOLOADed key deletion method. Removes the named attribute from the working object. Performs lcfirst on the attribute named in the message.

      $self->setFoo("bario");
      $self->foo(); # returns "bario";
    
      $self->deleteFoo();
      $self->foo(); # returns undef

PRIVATE INSTANCE METHODS

  • $self->_init();

    Abstract callback method invoked after object creation (called from new()).

    Override in subclass to handle additional logic if needed.

SEE ALSO

This file is part of OP.