-
Notifications
You must be signed in to change notification settings - Fork 1
Expand file tree
/
Copy pathObject.lua
More file actions
112 lines (102 loc) · 3.13 KB
/
Object.lua
File metadata and controls
112 lines (102 loc) · 3.13 KB
1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
28
29
30
31
32
33
34
35
36
37
38
39
40
41
42
43
44
45
46
47
48
49
50
51
52
53
54
55
56
57
58
59
60
61
62
63
64
65
66
67
68
69
70
71
72
73
74
75
76
77
78
79
80
81
82
83
84
85
86
87
88
89
90
91
92
93
94
95
96
97
98
99
100
101
102
103
104
105
106
107
108
109
110
111
112
local class = require "class"
---@class Object: class
---@type fun(): Object
local Object = class("Object")
Object.properties = {}
---Copies over existing properties in the base class into the derived class.
---Properties are copied over to simplify overriding their behavior.
---@param derived Object
function Object:inherit(derived)
local properties = setmetatable({}, {
__index = function(object, name)
local property = {}
object[name] = property
return property
end
})
for name, property in pairs(self.properties) do
properties[name] = {
get = property.get,
set = property.set
}
end
derived.properties = properties
end
---Deals with property getters.
---@param key string
---@return any
function Object.metatable:index(key)
local property = rawget(self.properties, key)
if property then
local get = property.get
if get then
return get(self)
end
error("property " .. self.classname .. "." .. key .. " is not readable", 2)
end
end
---Deals with property setters.
---@param key string
---@param value any
function Object.metatable:__newindex(key, value)
local property = rawget(self.properties, key)
if property then
local set = property.set
if set then
set(self, value)
else
error("property " .. self.classname .. "." .. key .. " is not writable", 2)
end
else
rawset(self, key, value)
end
end
---Returns the properties table of the class or object.
---@return table properties
local function getProperties(self)
assert(class.isClass(self), "properties are class specific")
return self.properties
end
---Adds a read-only property for a field.
---@param name string The name of the property.
---@param field? string The name of the backing field; defaults to `_<name>`.
function Object:addReadonly(name, field)
local properties = getProperties(self)
field = field or ("_" .. name)
properties[name].get = function(self)
return self[field]
end
end
---Adds an Event property which uses the setter to add a new handler
---@param name string The name of the Event property.
---@param field? string The name of the backing field; defaults to `_<name>`.
function Object:addEvent(name, field)
local properties = getProperties(self)
field = field or ("_" .. name)
properties[name].get = function(object)
return object[field]
end
properties[name].set = function(object, value)
object[field]:add(value)
end
end
---Adds a property for a field with an event handler.
---@param name string The name of the property.
---@param field? string The name of the backing field; defaults to `_<name>`.
---@param event? string The name of the event; defaults to `_on<Name>Change`.
function Object:addProperty(name, field, event)
local properties = getProperties(self)
field = field or ("_" .. name)
event = event or ("_on" .. name:gsub("^%l", string.upper) .. "Change")
properties[name].get = function(object)
return object[field]
end
properties[name].set = function(object, value)
local oldValue = object[field]
if oldValue ~= value then
object[field] = value
object[event](object, oldValue)
end
end
end
return Object