📜 ⬆️ ⬇️

Prototype OOP for Lua

Hi, I invented my bike to implement the prototype approach of the PLO in Lua.

The main chips


Let's go straight to the examples.
')
--   local object = require("object") --   ,      local HelloClass = object:extend(function(class) --  () function class:init(name) self.name = name end --   function class:sayHello() print("Hello " .. self.name) end end) local hello = HelloClass:new("John") hello:sayHello() 


As you can see, all the magic lies in the extend (traits ..., f) method, which extends the current object.

You can define variables inside

 local object = require("object") local Status = object:extend(function(status) status.HTTP_200_OK = {200, "OK"} status.HTTP_405_METHOD_NOT_ALLOWED = {404, "Method not allowed"} end) print(Status.HTTP_200_OK[2]) 


Static methods

Where do without them ...

 local object = require("object") local MathUtils = object:extend(function(class) function class.square(x) return x * x end end) --    print(MathUtils.square(10)) --         print(MathUtils:new().square(10)) -- 100 


Constructor

When creating a new instance, the init () constructor is called via new ().

 local Counter = object:extend(function(class) -- ,   -  (   ) function class:init(initial) self.ticks = initial or 0 end function class:tick() self.ticks = self.ticks + 1 end function class:getTicks() return self.ticks end end) local c = Counter:new() c.tick() c.tick() print(c:getTicks() == 2) 


Inheritance and Overloading Methods

As I mentioned, inheritance is done as single inheritance, that is, you can only inherit from one “class”, but there are still treitures that we will talk about later. Overloading does not cause any issues.

 local Shape = object:extend(function(class) function class:getArea() return 0 end end) local Square = Shape:extend(function(class) function class:init(side) self.side = side end --   function class:getArea() return self.side * self.side end end) local sq = Square:new(10) print("Area = " .. sq:getArea()) 


Calling the parent method

To do this, use the second parameter of the lambda function, which you pass to extend, which is a reference to the parent object (which you want to expand)

 local Foo = object:extend(function(class) function class:init(value) self.value = value end function class:say() print("Hello " .. self.value) end end) class Bar = Foo:extend(function(class, parent) function class:init(value) --    parent.init(self, value) end end) local foo = Foo:new("World") foo:say() --  "Hello World" local bar = Bar:new("World") bar:say() --  "Hello World" 


Treit

When there is a lack of multiple inheritance as in C ++, you can use traits that extend the functionality.

Just pass your traits to the top of the extend () arguments.

 local TraitX = function(trait) function trait:setX(x) self.x = x return self end function trait:getX() return self.x end end local A = object:extend(TraitX, function(class) function class:say() print(self.x) end end) A:new():setX(10):say() 


Useful features

is_instanceof (self, instance) - returns true if instance is a direct or indirect descendant of self

 local ClassA = object:extend() local ClassB = object:extend() local obj_a = ClassA:new() local obj_b = ClassB:new() print(obj_a:is_instanceof(ClassA)) -- true print(obj_a:is_instanceof(object)) -- true print(obj_a:is_instanceof(ClassB)) -- false 


i s_typeof (self, instance) - returns true if instance is a direct descendant of self

 local ClassA = object:extend() local ClassB = object:extend() local obj_a = ClassA:new() local obj_b = ClassB:new() print(obj_b:is_typeof(ClassA)) -- false print(obj_b:is_typeof(ClassB)) -- true 


LuaJIT

Alternatively, work in LuaJIT is supported.

Where is the code, Carl?

Here

Source: https://habr.com/ru/post/259145/


All Articles