# Class `std.object`

Prototype-based objects.

This module creates the root prototype object from which every other object is descended. There are no classes as such, rather new objects are created by cloning an existing object, and then changing or adding to the clone. Further objects can then be made by cloning the changed object, and so on.

Objects are cloned by simply calling an existing object, which then serves as a prototype from which the new object is copied.

Note that Object methods are stored in the `__index` field of their metatable, and so cannot also use `__index` to lookup references with square brackets. See std.container objects if you want to do that.

## Prototype Chain

    table
     `-> Object

## Objects

std.object.Object | Root object.

## Functions

std.object.clone (obj, ...) | Clone an Object.
std.object.mapfields (obj, src[, map={}]) | Return obj with references to the fields of src merged in.
std.object.prototype (x) | Type of an object, or primitive.

## Metamethods

std.object:__call (...) | Return a clone of this object, and its metatable.
std.object:__pairs () | Return an in-order iterator over public object fields.
std.object:__tostring () | Return a string representation of this object.

## Objects

std.object.Object
  Root object.

  Changing the values of these fields in a new object will change the corresponding behaviour.

  ### Fields:

  - _init table or function object initialisation (default {})
  - _functions table module functions omitted when cloned
  - _type string object name (default "Object")

  ### See also:

  __call

  ### Usage:

  -      -- `_init` can be a list of keys; then the unnamed `init_1` through
         -- `init_m` values from the argument table are assigned to the
         -- corresponding keys in `new_object`.
         local Process = Object {
           _type = "Process",
           _init = { "status", "out", "err" },
         }
         local process = Process {
           procs[pid].status, procs[pid].out, procs[pid].err, -- auto assigned
           command = pipeline[pid],                           -- manual assignment
         }

  -      -- Or it can be a function, in which the arguments passed to the
         -- prototype during cloning are simply handed to the `_init` function.
         local Bag = Object {
           _type = "Bag",
           _init = function (obj, ...)
             for e in std.elems {...} do
               obj[#obj + 1] = e
             end
             return obj
           end,
         }
         local bag = Bag ("function", "arguments", "sent", "to", "_init")

## Functions

Methods

std.object.clone (obj, ...)
  Clone an Object.

  Objects are essentially tables of `field_n = value_n` pairs.

  Normally `new_object` automatically shares a metatable with `proto_object`. However, field names beginning with "_" are private, and moved into the object metatable during cloning. So, adding new private fields to an object during cloning will result in a new metatable for `new_object` that also happens to contain a copy of all the entries from the `proto_object` metatable.

  While clones of Object inherit all properties of their prototype, it's idiomatic to always keep separate tables for the module table and the root object itself: That way you can't mistakenly engage the slower clone-from-module-table process unnecessarily.

  ### Parameters:

  - obj Object an object
  - ... a list of arguments if obj._init is a function, or a single table if obj._init is a table.

  ### Returns:

  Object a clone of obj

  ### See also:

  __call

  ### Usage:

       local object = require "std.object"  -- module table
       local Object = object {}             -- root object
       local o = Object {
         field_1 = "value_1",
         method_1 = function (self) return self.field_1 end,
       }
       print (o.field_1)                    --> value_1
       o.field_2 = 2
       function o:method_2 (n) return self.field_2 + n end
       print (o:method_2 (2))               --> 4
       os.exit (0)

std.object.mapfields (obj, src[, map={}])
  Return obj with references to the fields of src merged in.

  More importantly, split the fields in src between obj and its metatable. If any field names begin with "_", attach a metatable to obj by cloning the metatable from src, and then copy the "private" `_` prefixed fields there.

  You might want to use this function to instantiate your derived object clones when the src._init is a function -- when src._init is a table, the default (inherited unless you overwrite it) clone method calls mapfields automatically. When you're using a function `_init` setting, clone doesn't know what to copy into a new object from the `_init` function's arguments... so you're on your own. Except that calling mapfields inside `_init` is safer than manually splitting `src` into `obj` and its metatable, because you'll pick up any fixes and changes when you upgrade stdlib.

  ### Parameters:

  - obj table destination object
  - src table fields to copy int clone
  - map table key renames as `{old_key=new_key, ...}` (default {})

  ### Returns:

  table obj with non-private fields from src merged, and a metatable with private fields (if any) merged, both sets of keys renamed according to map

  ### Usage:

       myobject.mapfields = function (obj, src, map)
         object.mapfields (obj, src, map)
         ...
       end

std.object.prototype (x)
  Type of an object, or primitive.

  It's conventional to organise similar objects according to a string valued _type field, which can then be queried using this function.

  Additionally, this function returns the results of ??? for file objects, or type otherwise.

  ### Parameters:

  - x anything

  ### Returns:

  string type of x

  ### Usage:

       local Stack = Object {
         _type = "Stack",

         __tostring = function (self) ... end,

         __index = {
           push = function (self) ... end,
           pop  = function (self) ... end,
         },
       }
       local stack = Stack {}
       assert (stack:prototype () == getmetatable (stack)._type)

       local prototype = Object.prototype
       assert (prototype (stack) == getmetatable (stack)._type)

       local h = io.open (os.tmpname (), "w")
       assert (prototype (h) == io.type (h))

       assert (prototype {} == type {})

## Metamethods

std.object:__call (...)
  Return a clone of this object, and its metatable.

  Private fields are stored in the metatable.

  ### Parameters:

  - ... arguments for prototype's _init

  ### Returns:

  Object a clone of the this object.

  ### See also:

  clone

  ### Usage:

       local Object = require "std.object" {} -- not a typo!
       new = Object {"initialisation", "elements"}

std.object:__pairs ()
  Return an in-order iterator over public object fields.

  ### Returns:

  1. function iterator function
  2. Object self

  ### Usage:

      for k, v in std.pairs (anobject) do process (k, v) end

std.object:__tostring ()
  Return a string representation of this object.

  First the object type, and then between { and } a list of the array part of the object table (without numeric keys) followed by the remaining key-value pairs.

  This function doesn't recurse explicity, but relies upon suitable `__tostring` metamethods in field values.

  ### Returns:

  string stringified object representation

  ### See also:

  tostring

  ### Usage:

      print (anobject)

generated by LDoc 1.4.3 Last updated 2018-09-03 17:48:42