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 std.object.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 table object initialisation (default {})
- _functions table module functions omitted when cloned
- _type string object name (default "Object")
See also:
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 std.object.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 std.object.Object an object
- ... a list of arguments if *obj.\_init* is a function, or a single table if *obj.\_init* is a table.
Returns:
-
std.object.Object
a clone of *obj*
See also:
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 std.object.mapfields automatically. When you're using a function `_init` setting, std.object.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 std.object.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 std.object.clone of this object, and its metatable.
Private fields are stored in the metatable.
Parameters:
- ... arguments for prototype's *\_init*
Returns:
-
std.object.Object
a clone of the this object.
See also:
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:
- std.object.Object iterator function
- std.object.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:
Usage:
print (anobject)