|
- local doc = require "wslua.doc"
- local fndef = require "wslua.fndef"
- local ty = require "wslua.ty"
-
- local misc = require "wslua.misc"
-
-
- doc.module{
- name = "wslua.class",
- what = "Class functionality in Lua",
- }
-
-
-
- local class = {}
-
- setmetatable(class, {__call = fndef({
- name = "class",
- what = "Create a class.",
- args = {
- {},
- {
- name = "data",
- type = ty.key{
- name = ty.string,
- base = #ty.table,
- what = ty.string,
- descr = #ty.string,
- fields = #ty.list(ty.key{
- name = ty.string,
- what = ty.string,
- descr = #ty.string,
- }),
- },
- what = "Class data.",
- fields = {
- {name = "name", what = "Human readable class name."},
- {name = "base", what = "Base class to inherit, defaults to `class.object`."},
- {name = "what", what = "Short description."},
- {name = "descr", what = "Longer class details."},
- {name = "fields", what = "Description of member variables."},
- },
- },
- },
- ret = {
- {
- type = ty.table,
- what = "Class table to be filled with functions.",
- descr = [[
- Every value assigned into this table is read-accessible through any object created from this class. Additionally,
- metamethods with well-known names are automatically inserted into the object metatable. All fields listed below are
- initially `nil` and intended to be provided by the user if desired, unless explicitly noted otherwise. Note that all
- values should be set before the first object is constructed or derived classes are created.
- ]],
- fields = {
- {
- name = "__new",
- type = #ty.Function,
- what = "Constructor function.",
- descr = [[
- Receives the arguments passed to the class constructor, and is then expected to modify the return value of a `__super`
- call to create and return an approriate object. Defaults to `function(...) return myclass.__super(...) end` if not
- provided.
- ]],
- },
- {
- name = "__super",
- type = #ty.Function,
- what = "Wrapped base class constructor to be called inside `__new`. Already provided.",
- descr = [[
- Passes all of its arguments to the constructor of the base class, and modifies the returned result to be an instance of
- the correct class. `__new` should assign relevant fields to the returned object to bring it into a valid state before
- returning it.
- ]],
- },
- {name = "__add" , type = #ty.Function, what = "`__add` metamethod." },
- {name = "__band" , type = #ty.Function, what = "`__band` metamethod." },
- {name = "__bnot" , type = #ty.Function, what = "`__bnot` metamethod." },
- {name = "__bor" , type = #ty.Function, what = "`__bor` metamethod." },
- {name = "__bxor" , type = #ty.Function, what = "`__bxor` metamethod." },
- {name = "__call" , type = #ty.Function, what = "`__call` metamethod." },
- {name = "__concat" , type = #ty.Function, what = "`__concat` metamethod." },
- {name = "__div" , type = #ty.Function, what = "`__div` metamethod." },
- {name = "__eq" , type = #ty.Function, what = "`__eq` metamethod." },
- {name = "__idiv" , type = #ty.Function, what = "`__idiv` metamethod." },
- {
- name = "__index",
- type = #ty.Function,
- what = "`__index` metamethod.",
- descr = [[
- This function is called **before** class indexing and inheritance have taken place, be careful not to overwrite class
- functionality with this!
- ]],
- },
- {name = "__le" , type = #ty.Function, what = "`__le` metamethod." },
- {name = "__len" , type = #ty.Function, what = "`__len` metamethod." },
- {name = "__lt" , type = #ty.Function, what = "`__lt` metamethod." },
- {name = "__mod" , type = #ty.Function, what = "`__mod` metamethod." },
- {name = "__mul" , type = #ty.Function, what = "`__mul` metamethod." },
- {name = "__newindex", type = #ty.Function, what = "`__newindex` metamethod."},
- {name = "__pow" , type = #ty.Function, what = "`__pow` metamethod." },
- {name = "__shl" , type = #ty.Function, what = "`__shl` metamethod." },
- {name = "__shr" , type = #ty.Function, what = "`__shr` metamethod." },
- {name = "__show" , type = #ty.Function, what = "`__show` metamethod." },
- {name = "__sub" , type = #ty.Function, what = "`__sub` metamethod." },
- {name = "__tostring", type = #ty.Function, what = "`__tostring` metamethod."},
- {name = "__unm" , type = #ty.Function, what = "`__unm` metamethod." },
- },
- },
- },
- ex = [[
- local class = require "wslua.class"
- local animal = class{name = "animal")
- function animal.__new(name) return animal.__super():set{name = name} end
- function animal:getName() return self.name end
-
- local cat = class{name = "cat", base = animal}
- function cat.__new(name) return cat.__super(name) end
- function cat:noise() return "meow" end
-
- local dog = class{name = "dog", base = animal}
- function dog.__new(name) return dog.__super(name) end
- function dog:noise() return "woof" end
-
- local garfield = cat("garfield")
- print(garfield:getName(), garfield:noise())
-
- local snoopy = dog("snoopy")
- print(snoopy:getName(), snoopy:noise())
- ]],
- },
- function(_, data)
- data.base = data.base or (not data.__is_object and class.object or false)
- require "wslua.core.doc" .handler.class(data)
- local ret = {}
- ret.name = data.name
- ret.base = data.base
- local mt = {}
- mt.__index = ret.base or nil
- mt.__tostring = function() return data.name end
-
- ret.__super = function(...)
- return setmetatable(ret.base and ret.base(...) or {}, {
- class = ret ,
- __add = ret.__add ,
- __sub = ret.__sub ,
- __mul = ret.__mul ,
- __div = ret.__div ,
- __mod = ret.__mod ,
- __pow = ret.__pow ,
- __unm = ret.__unm ,
- __idiv = ret.__idiv ,
- __band = ret.__band ,
- __bor = ret.__bor ,
- __bxor = ret.__bxor ,
- __bnot = ret.__bnot ,
- __shl = ret.__shl ,
- __shr = ret.__shr ,
- __concat = ret.__concat ,
- __len = ret.__len ,
- __eq = ret.__eq ,
- __lt = ret.__lt ,
- __le = ret.__le ,
- __index = ret.__index
- and function(obj, k)
- local r = ret.__index(obj, k)
- if r ~= nil then return r else return ret[k] end
- end
- or ret,
- __newindex = ret.__newindex,
- __call = ret.__call ,
- __tostring = ret.__tostring,
- __show = ret.__show ,
- })
- end
-
- function mt:__call(...)
- return (rawget(self, "__new") or self.__super)(...)
- end
-
- return setmetatable(ret, mt)
- end)})
-
-
-
- doc.section "The `class.object` common superclass"
-
-
-
- class.object = class{
- name = "class.object",
- what = "Common superclass for all classes.",
- descr = "Provides some basic functionality.",
- __is_object = true,
- }
-
-
- class.object.class = fndef({
- name = "class.object:class",
- what = "Returns the class table of an object.",
- args = {
- {name = "self", type = ty.class(class.object)},
- },
- ret = {
- {type = ty.table, what = "Class table of `self`."},
- },
- },
- function(self)
- return getmetatable(self).class
- end)
-
-
- class.object.instanceof = fndef({
- name = "class.object:instanceof",
- what = "Checks whether `self` is an instance of `x` or its derived classes.",
- args = {
- {name = "self", type = ty.class(class.object)},
- {name = "x", type = ty.table, what = "Class table."},
- },
- ret = {
- {type = ty.boolean},
- },
- },
- function(self, x)
- local class = self:class()
- while class do
- if x == class then return true end
- class = class.base
- end
- return false
- end)
-
-
- class.object.set = fndef({
- name = "class.object:set",
- what = "Update fields of the object using the fields from the table.",
- args = {
- {name = "self", type = ty.class(class.object)},
- {name = "values", type = ty.table, what = "Table to take update values from."},
- },
- ret = {
- {type = ty.class(class.object), what = "Updated `self`."},
- },
- },
- function(self, values)
- for k, v in pairs(values) do self[k] = v end
- return self
- end)
-
-
- class.object.dup = fndef({
- name = "class.object:dup",
- what = "Create a shallow copy of `self`.",
- args = {
- {name = "self", type = ty.class(class.object)},
- },
- ret = {
- {type = ty.class(class.object)},
- },
- },
- function(self)
- local ret = {}
- for k, v in pairs(self) do
- ret[k] = v
- end
- return setmetatable(ret, getmetatable(self))
- end)
-
-
- class.object.show = fndef({
- name = "class.object:show",
- what = "Convert the object to a string using `wslua.misc.show`.",
- args = {
- {name = "self", type = ty.class(class.object)},
- {name = "opts", type = misc.showopts, what = "Conversion options."},
- },
- ret = {
- {type = ty.string},
- },
- see = {
- {module = "wslua.misc", name = "misc.show"},
- }
- },
- function(self, opts)
- return misc.show(self, opts)
- end)
-
-
- return class
|