Middleclass 4.x Object-Orientation for Lua

Showcase your libraries, tools and other projects that help your fellow love users.
User avatar
lukems
Prole
Posts: 6
Joined: Sun Jan 29, 2017 4:09 pm

Re: [Lib] Middleclass 4.0.0. Object-Orientation for Lua

Post by lukems »

I'm using a lot of your libraries lately, great stuff, thanks for sharing them with us!
While using Middleclass I was wondering if you guys have a nice way to declare properties with it.
Do note that I'm still learning my way through Lua and Löve, coming from Python :nyu:
This is how I'm currently doing it:

Code: Select all

local class = require('middleclass')

Rect = class('Rect')

local __setters = {}
local __getters = {}
__getters.__index = __getters
__setters.__index = __setters

function __getters:right()
    return self.x + self.w
end

function __setters:right(v)
    self.x = self.x + v - self.right
end

function Rect:initialize(x, y, w, h)
    self.x = x
    self.y = y
    self.w = w
    self.h = h
end

function Rect:__index(k)
    return __getters[k](self)
end

function Rect:__newindex(k, v)
    local fn = __setters[k]
    if fn ~= nil then
        fn(self, v)
    else
        rawset(self, k, v)
    end
end
User avatar
kikito
Inner party member
Posts: 3153
Joined: Sat Oct 03, 2009 5:22 pm
Location: Madrid, Spain
Contact:

Re: [Lib] Middleclass 4.0.0. Object-Orientation for Lua

Post by kikito »

Hi there! Thanks for your kind words.

Let me start by saying that I am not a huge fan of getters/setters in Lua. In other languages, I can accept them; for example in ruby, they are integrated in the language's message-passing mechanism.

But in Lua they are extra syntactic sugar, and risk making things more "magical" (unexpected to someone unfamiliar with the code).

That said, your approach is a good approximation at implementing properties. I would suggest some changes though.
  • I would put the properties-related code in a mixin, so that it can be easily reused by multiple classes without having to do "the metatable dance" on every class.
  • I would still require getter and setter methods. That way, if someone (like me) doesn't want to use properties, they have the option to use the "old fashioned" methods
  • Given the previous point, I would build the properties by convention: if there is a set_xxx method, then xxx is setable via obj.xxx = too. Similarly, if there is a get_xxx method, then xxx is gettable via obj.xxx. This way you would not even need the 'setters' or 'getters' variables.
That would give us this mixin:

Code: Select all

-- properties.lua
local Properties = {}

function Properties:__index(k)
  return self['get_' .. k]
end

function Properties:__newIndex(k, v)
    local fn = self['set_' .. k]
    if fn then
      fn(self, v)
    else
      rawset(self, k, v)
    end
  end
end

return Properties
Usage:

Code: Select all

local class = require('middleclass')
local Properties = require('properties')

local Rect = class('Rect'):include(Properties)

function Rect:initialize(x, y, w, h)
  self.x = x
  self.y = y
  self.w = w
  self.h = h
end

function Rect:get_right()
  return self.x + self.w
end

function Rect:set_right(right)
  self.x = self.x + right - self.right
end

r = Rect:new(10,10, 100, 100)

print(r.right) -- 110
print(r:get_right()) -- 110
r.right = 200
print(r.right) -- 200
print(r.x) -- 100
r.name = 'peter'
print(r.name) -- peter
When I write def I mean function.
User avatar
lukems
Prole
Posts: 6
Joined: Sun Jan 29, 2017 4:09 pm

Re: [Lib] Middleclass 4.0.0. Object-Orientation for Lua

Post by lukems »

Thanks for your quick answer, that looks great!

Maybe I'll be able to drop those properties in the future, when I get over my Python bias...

I'm happy to say that your nice and clean implementation is also faster, taking only 66% of the time mine did on some tests.
Great news, considering I'm going to use those Rect's a lot!

I've done two changes on properties.lua to get it working here.
  • return self['get_' .. k] was raising a stack overflow error so I'm now using self.class.__instanceDict["get_" .. k] instead;
  • When a nil value was (not) found, an error was raised (by trying to call it as a function), so I've included a check.
(And a minor tweak, comparing things specifically against nil gave it a big performance boost here :ultrashocked:).

Code: Select all

-- properties.lua
local Properties = {}

function Properties:__index(k)
    local getter = self.class.__instanceDict["get_" .. k]
    if getter ~= nil then
        return getter(self)
    end
end

function Properties:__newindex(k, v)
    local setter = self["set_" .. k]
    if setter ~= nil then
        setter(self, v)
    else
        rawset(self, k, v)
    end
end

return Properties

Maybe you could include this mixin as a recipe/example at middleclass library wiki. For people like me :ultrahappy:
User avatar
kikito
Inner party member
Posts: 3153
Joined: Sat Oct 03, 2009 5:22 pm
Location: Madrid, Spain
Contact:

Re: [Lib] Middleclass 4.0.0. Object-Orientation for Lua

Post by kikito »

Great news, considering I'm going to use those Rect's a lot!
If you are planning to use it a lot, for intensive calculus etc, I would recommend you to measure how fast it is to not use middleclass at all too. Middleclass (and, in fact, any object-oriented library) is not a good fit for super-tight intensive calculations. For example, I would not use it for vectors or matrixes. For those, I think plain numbers + functions work best. There is no metatables - and there is no tables either. So your intensive code generates as little garbage as possible. That's what I did for the rectangles in bump.. Vrld has done something for vectors in vector-light.
I've done two changes on properties.lua to get it working here.
Ok!
(And a minor tweak, comparing things specifically against nil gave it a big performance boost here
That is ... unintuitive. As far as I know, if x is logically equivalent to if x ~= nil when x can't be false. And it seems that the first one should be faster since it is doing less. But that's efficiency for you; one never knows until the test is run.
When I write def I mean function.
User avatar
DanielPower
Citizen
Posts: 50
Joined: Wed Apr 29, 2015 5:28 pm

Re: [Lib] Middleclass 4.0.0. Object-Orientation for Lua

Post by DanielPower »

Thank you again Kikito for your fantastic libraries. I use middleclass in all of my projects, and almost always end up using bump and inspect. I also wanted to mention that your blog taught be a lot about writing and using modules, and oop. I'll be upgrading to middleclass 4 when I get the time to start working on my game again. I'll report back with results compared to middleclass 3.
User avatar
kikito
Inner party member
Posts: 3153
Joined: Sat Oct 03, 2009 5:22 pm
Location: Madrid, Spain
Contact:

Re: [Lib] Middleclass 4.0.0. Object-Orientation for Lua

Post by kikito »

DanielPower wrote:Thank you again Kikito for your fantastic libraries. I use middleclass in all of my projects, and almost always end up using bump and inspect. I also wanted to mention that your blog taught be a lot about writing and using modules, and oop. I'll be upgrading to middleclass 4 when I get the time to start working on my game again. I'll report back with results compared to middleclass 3.
Cool :ultrahappy: Remember that there's an Update Guide.
When I write def I mean function.
User avatar
lukems
Prole
Posts: 6
Joined: Sun Jan 29, 2017 4:09 pm

Re: [Lib] Middleclass 4.0.0. Object-Orientation for Lua

Post by lukems »

kikito wrote:
Great news, considering I'm going to use those Rect's a lot!
If you are planning to use it a lot, for intensive calculus etc, I would recommend you to measure how fast it is to not use middleclass at all too. Middleclass (and, in fact, any object-oriented library) is not a good fit for super-tight intensive calculations. For example, I would not use it for vectors or matrixes. For those, I think plain numbers + functions work best. There is no metatables - and there is no tables either. So your intensive code generates as little garbage as possible. That's what I did for the rectangles in bump.. Vrld has done something for vectors in vector-light.
I've done two changes on properties.lua to get it working here.
Ok!
(And a minor tweak, comparing things specifically against nil gave it a big performance boost here
That is ... unintuitive. As far as I know, if x is logically equivalent to if x ~= nil when x can't be false. And it seems that the first one should be faster since it is doing less. But that's efficiency for you; one never knows until the test is run.
Good to know, and thanks for all the info and advices!
When I achieve a running'ish state on my project, if things are not fast enough and the Rect looks guilty, I'll check those cases you've provided and try to do it like a pro :cool:
I'm hoping, though, that as long as I don't make poor use of them on pathfinding, fov and procedural map generation things are going to be ok (considering that I'm doing a Lua/love2d port of my Python/py-sdl2 thing, every piece of code runs way faster so far).
User avatar
DanielPower
Citizen
Posts: 50
Joined: Wed Apr 29, 2015 5:28 pm

Re: [Lib] Middleclass 4.0.0. Object-Orientation for Lua

Post by DanielPower »

My bad, I didn't look at the post date. It turns out I've been using Middleclass 4.0 for a year. Which explains why I didn't know there was ever a global Object class to begin with. I suppose it's time to upgrade to 4.10, I'm only half a year late for that :p
User avatar
kikito
Inner party member
Posts: 3153
Joined: Sat Oct 03, 2009 5:22 pm
Location: Madrid, Spain
Contact:

Re: [Lib] Middleclass 4.0.0. Object-Orientation for Lua

Post by kikito »

DanielPower wrote:It turns out I've been using Middleclass 4.0 for a year
^^ that made me chuckle a little. I don't update middleclass very often now, because I think it is pretty much done. I can try to make it a little bit faster, but that's pretty much it.
When I write def I mean function.
Zireael
Party member
Posts: 139
Joined: Fri Sep 02, 2016 10:52 am

Re: [Lib] Middleclass 4.0.0. Object-Orientation for Lua

Post by Zireael »

I just realized I am using the outdated Lua module keyword in my project. :oops:

I am looking for an OOP implementation that allows multiple inheritance. I looked through git and github wiki and I am not sure whether middleclass supports it or not.
Post Reply

Who is online

Users browsing this forum: No registered users and 56 guests