summaryrefslogtreecommitdiff
path: root/Data/BuiltIn/Libraries/GameLab/Class.lua
blob: db8e2b2a281c8530ed30bc5361f2056581ab3d06 (plain)
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
113
-- 声明类型

-- 保留方法:New, Ctor, Is, get_, set_
-- 保留字段:_type, _base

local TRACKCLASSINSTANCES = false
local PROPERTY = true

local index = function(self, key) 
    local c = getmetatable(self)

    local field = rawget(c, key)
    if field then 
        return field
    end 
    
    local getter = rawget(c, 'get_' .. key)
    if getter then 
        return getter(self)
    end 
    
    return nil 
end 

local newindex = function(self, key, value) 
    local c = getmetatable(self)

    local setter = rawget(c, 'set_' .. key)
    if setter then 
        setter(self, value)
        return 
    end 

    rawset(self, key, value)
end 

local newclass = function (name, ctor)
    local c = {}

    local pkg = "unknown"
    local short = "unknown" 
    if type(name) == "string" then 
        pkg = string.match(name, "^(.+)%.%w+$")
        short = string.match(name, "%.*(%w+)$")
    end 
    
    c._type = { 
        mode = "lua",
        name = short,
        package = pkg,
        fullName = name
    }

    if PROPERTY then 
        c.__index = index
        c.__newindex = newindex
    else 
        c.__index = c
    end

    c.New = function(...) 
        local obj = {} 
        setmetatable(obj, c)
        obj:Ctor(...)
        return obj
    end

    c.Is = function(self, klass) 
        local m = getmetatable(self)
        while m do 
            if m == klass then 
                return true 
            end
            m = m._base
        end
        return false
    end 

    if ctor and type(ctor) == "function" then 
        c.Ctor = ctor
    end 

    local mt = {} 

    mt.__call = function(dummy, ...)
        return c.New(...)
    end 

    setmetatable(c, mt)

    return c
end

local class = function(name, ctor)
    local c = newclass(name, ctor)
    
    c.Extend = function(childName)
        local child = newclass(childName) 
        if c then 
            setmetatable(child, c)
            child._base = c
        end 
        return child
    end

    c._base = nil

    return c
end  

GameLab.Class = class

return class