Perfect OOP Library

General discussion about LÖVE, Lua, game development, puns, and unicorns.
Post Reply
be-thomas
Prole
Posts: 9
Joined: Fri Apr 29, 2022 8:22 am

Perfect OOP Library

Post by be-thomas »

There are a lot of OOP libraries. But they have their own styles.
I recently made the perfect one which can be found here - https://github.com/be-thomas/createClass

Why it is perfect?

See the features -
1) simple usage & implementation
2) small (one file, just 140 lines)
3) support for static and instance properties
4) easy inline getters/setters
5) support for `super`
6) support for printing classes & objects with proper indentation

Yep, you can print classes too, the and it preserves indentation(even nested indentations).
Example :-

Code: Select all

class {
  set: function: 0x010085a628,
  super: class {
    constructor: function: 0x0100864db0,
    set: function: 0x010085a628,
    _: table: 0x0100864c10,
  },
  constructor: function: 0x0100867298,
  _: table: 0x0100867040,
}

object {
  set: function: 0x010085a628,
  super: table: 0x0100867348,
  constructor: function: 0x0100867298,
  _: table: 0x01008674e0,
}
This is supposed to be minimal in terms of syntax.

Why to use this instead of other heavy libraries?
We are bound to have a lot of objects & classes in our games. It is always a good idea to reduce the complexity and memory usage.
Even the code of those OOP libraries are pretty complex taking up a lot of resources.
Some say OOP in 100 lines but when you see the code, it is actually supposed to be of 400-500 lines but shortened through some obfuscator!

Credits: Forked & improved from https://github.com/jonstoler/class.lua
User avatar
GVovkiv
Party member
Posts: 674
Joined: Fri Jan 15, 2021 7:29 am

Re: Perfect OOP Library

Post by GVovkiv »

For some reasons, it's remind me of https://xkcd.com/927/ haha
Anyway, good job
User avatar
ddabrahim
Party member
Posts: 183
Joined: Mon May 17, 2021 8:05 pm
Contact:

Re: Perfect OOP Library

Post by ddabrahim »

I was just looking for an OOP library. It is doing me headache in Lua and my code is a nightmare to debug. I really like the simple syntax and being small and light weight. I'm certainly gong to give it a try and see if it can save me from insanity :D
Thanks for sharing!
User avatar
zorg
Party member
Posts: 3446
Joined: Thu Dec 13, 2012 2:55 pm
Location: Absurdistan, Hungary
Contact:

Re: Perfect OOP Library

Post by zorg »

I'd question your humbleness, referring to that as perfect, but it is indeed another class library, at the very least.

I read the readme on github, i feel like there are some interesting choices in there;
like the weird usage of the word "Object", when you intermix that with "Instance" in some places... I'd just use Class and Instance.
or the fact that properities are bloated into tables since getters and setters are required to be in there with them. (and the example code wasn't too clear why changing a properity didn't affect what was printed out)

Oh, and the superclass stuff copies members if i read the code correctly, instead of using the __index metamethod, which is further bloat.

Well, to each their own, of course. :3
(BTW the original of this fork had similar issuesimplementation choices, from what i've seen)
Me and my stuff :3True Neutral Aspirant. Why, yes, i do indeed enjoy sarcastically correcting others when they make the most blatant of spelling mistakes. No bullying or trolling the innocent tho.
be-thomas
Prole
Posts: 9
Joined: Fri Apr 29, 2022 8:22 am

Re: Perfect OOP Library

Post by be-thomas »

About the use of "object", I use it since Java was my first language where I learn't OOP.
The mixing of instance and object is because, I only edited parts of the README from the original fork. I Will rectify this.

The properties are stored in '_' inside the table. This is a way to support getters & setters.
This is also the reason why changing a property didn't affect what was printed out. Because new properties are stored inside '_'
I believe getters & setters are pretty much useless. And where it is useful(input validation), you would write your own code anyways.
removing getters & setters should actually make it a lot more "barebones", I'm thinking to do that, let me know your thoughts on this.

The superclass copies itself when you create a subclass. Well, this is to support inheritance chaining.
I could do it without that, but then I would have to maintain a table(say '_') to maintain all the classes inherited from.
This option does sound better. open to suggestions.
User avatar
pgimeno
Party member
Posts: 3581
Joined: Sun Oct 18, 2015 2:58 pm

Re: Perfect OOP Library

Post by pgimeno »

be-thomas wrote: Sat Apr 30, 2022 12:42 pm I believe getters & setters are pretty much useless. And where it is useful(input validation), you would write your own code anyways.
You haven't used Delphi/Lazarus very much, right? :cool: Try counting how many properties there are here: https://raw.githubusercontent.com/User4 ... ontrols.pp and how many of them are used for input validation.

True properties are very useful, far beyond mere validators. A typical use of a property setter is to notify other objects of a change in a value, rather than having the other objects monitor said value - a way of saving CPU time. Or in general, updating whatever is affected by a certain change. As for a property getter, it's useful to make it behave as if something is a field but it is actually calculated; for example, position in tiles could be a property that is calculated from the position in pixels.

Your implementation of properties is very poor. True properties should transparently behave like fields. This thread discusses a bit about them: viewtopic.php?f=4&t=85244

You can remove properties, but then I don't think I will have any reason to use your lib instead of rxi's Classic, which is just 68 lines. And in fact, unless the implementation is improved, if I want properties I better implement them on top of Classic than use this.

be-thomas wrote: Sat Apr 30, 2022 12:42 pm The superclass copies itself when you create a subclass. Well, this is to support inheritance chaining.
I could do it without that, but then I would have to maintain a table(say '_') to maintain all the classes inherited from.
This option does sound better. open to suggestions.
Copying is a tradeoff - it saves CPU time at the cost of memory. You can chain metatables in such way that when class A does not have property X, the metatable of A redirects the lookup to A's parent, and in turn, when A's parent doesn't have X, its metatable redirects the lookup into A's parent's parent, and so on up to the base class; that may be slower sometimes (if JIT-compiled, it won't make any difference), but it's more memory-efficient. Classic only copies fields that start with __ because it assumes them to be metamethods, therefore they need to be copied to the new class in order for the class to properly behave as the metatable of itself.
be-thomas
Prole
Posts: 9
Joined: Fri Apr 29, 2022 8:22 am

Re: Perfect OOP Library

Post by be-thomas »

I was able to add support for watchers with ZERO overhead.

Here is example watcher :-

Code: Select all

local createClass = require("createClass")

local Chicken = createClass()
Chicken:set({
    name = "height",
    default_value = 1
})

local ch = Chicken()
ch:watch("height", function(newValue, oldValue)
    print(("Watcher 1 : %d => %d"):format(oldValue, newValue))
end)
ch:watch("height", function(newValue, oldValue)
    print(("Watcher 2: Yep, I saw it too, %d changed into %d !"):format(oldValue, newValue))
end)

ch.height = 15
print(ch.height)
Output :-

Code: Select all

Watcher 1 : 1 => 15
Watcher 2: Yep, I saw it too, 1 changed into 15 !
15
The new code is updated on the repo. However, the README.md is not yet updated.
So, how does this have ZERO overhead?
By default __index uses table for inheritance, and __newindex doesn't exist at all. But as soon as you add your first watchable property calling set(), the Class changes the __index into a function, and also assigns __newindex with function.
It also starts using `_` property only after you add the first watchable property.
Other Improvements: now the whole table is not copied when inheriting
So yeah, performance is well maintained.
User avatar
Gunroar:Cannon()
Party member
Posts: 1091
Joined: Thu Dec 10, 2020 1:57 am

Re: Perfect OOP Library

Post by Gunroar:Cannon() »

If it's perfect that means it can make me a cheeseburger :huh:

Wow, that watcher looks useful. Nice lib.
The risk I took was calculated,
but man, am I bad at math.

-How to be saved and born again :huh:
be-thomas
Prole
Posts: 9
Joined: Fri Apr 29, 2022 8:22 am

Re: Perfect OOP Library

Post by be-thomas »

Gunroar:Cannon() wrote: Mon May 02, 2022 12:07 am If it's perfect that means it can make me a cheeseburger :huh:
Sure it can!
This is how you do it:-

Code: Select all

local createClass = require("createClass")

local CheeseBurger = createClass()
-- here you have it
local cheeseburger_for_gunroar = CheeseBurger()
Bon Appétit! :ultraglee:
User avatar
Gunroar:Cannon()
Party member
Posts: 1091
Joined: Thu Dec 10, 2020 1:57 am

Re: Perfect OOP Library

Post by Gunroar:Cannon() »

I knew it! :brows:
The risk I took was calculated,
but man, am I bad at math.

-How to be saved and born again :huh:
Post Reply

Who is online

Users browsing this forum: Bing [Bot] and 2 guests