Not a member of Pastebin yet?
Sign Up,
it unlocks many cool features!
- -- Point Class
- -- Prototype of the Point class
- -- If instance of class Point or instance of a class that inherits from this has no value, it will look here
- local Point = { name = "Point", x = 0, y = 0 }
- -- What now was a prototype table is now both a prototype and a metatable
- -- Once indexed, it will look inside of itself and make things like __tostring and other metaevents work
- Point.__index = Point
- -- The constructor function to create a new instance of class Point
- function Point:new(x, y)
- -- We override the predefined `self` variable pointing to `Point` table, and treat it like a new instance, THIS IS A GIMMICK
- self = {}
- -- Put some data into the instance depending on user input while remembering that if those are `nil` they'll use values in the `Point` prototype
- self.x = x
- self.y = y
- -- Assign the newly created instance to the `Point` table to use it as a metatable and a prototype
- return setmetatable(self, Point)
- end
- -- One of many metaevents, allowing us to nicely represent our object
- function Point:__tostring()
- return string.format("[%s] X:%d Y:%d", self.name, self.x, self.y)
- end
- function Point:setX(x)
- -- Assign OR remove (if `nil` is passed) the value from `x` key of the instance
- self.x = x
- end
- function Point:getX()
- -- If the instance holds `x`, return it, if not return the `x` value from `Point` prototype or if it doesn't have it, return nil
- return self.x
- end
- -- Rectangle Class
- -- Like previously with `Point`, we create a prototype table, but this time we know that we'll be inheriting from the `Point` class
- -- so there's no need to define `x` and `y` variables
- local Rectangle = { name = "Rectangle", w = 0, h = 0 }
- -- Make querying this object look in itself
- Rectangle.__index = Rectangle
- -- This is where inheritance really happens, after instance of `Rectangle` looked in itself, then the `Rectangle` prototype (because of the line above),
- -- make it look in the `Point` prototype / metatable
- setmetatable(Rectangle, { __index = Point })
- -- If this was not defined, calling `Rectangle:new()` would simply result in `Point:new()` being called
- function Rectangle:new(x, y, w, h)
- -- Create instance of the `Point` class and pass in variables from our new constructor
- self = Point:new(x, y)
- -- Define extra stuff this class needs, as before it will look in the `Rectangle` prototype and then the `Point` prototype
- self.w = w
- self.h = h
- -- Assign the instance as part of the `Rectangle` class, to use it's methods and prototype
- return setmetatable(self, Rectangle)
- end
- -- Override the `Point` __tostring and include extra stuff from this class
- function Rectangle:__tostring()
- return string.format("[%s] X:%d Y:%d W:%d H:%d", self.name, self.x, self.y, self.w, self.h)
- end
- function Rectangle:setW(w)
- -- Assign new value to the instance
- self.w = w
- end
- function Rectangle:getW()
- -- As before, look in self, `Rectangle` prototype and `Point` prototype, even though `Point` shuld never have it defined
- return self.w
- end
- -- Testing:
- local p = Point:new(1, 2)
- print(p) --> [Point] X:1 Y:2
- p:setX(123)
- print(p:getX()) --> 123
- local r = Rectangle:new()
- print(r:getX()) --> 0 (got from the `Point` prototype)
- r:setX(777)
- r:setW(999)
- print(r) --> [Rectangle] X:777 Y:0 W:999 H:0
Advertisement
Add Comment
Please, Sign In to add comment