This is a read-only snapshot of the ComputerCraft forums, taken in April 2020.
Konlab's profile picture

LOOa library - Classes with properties and member hiding in pure Lua

Started by Konlab, 25 March 2016 - 04:02 PM
Konlab #1
Posted 25 March 2016 - 05:02 PM
This is a library which helps you creating object oriented code in Lua.
I know, Luva and JaC are cool and probably better, but this is pure lua, so it will work both inside and outside CC and has properties and member hiding.

Features:
-Classes with short declaration
-Classes are instances themself
-Multi inheritance
-Member hiding (members beginning with '_')
-Properties (_get_<name> for declaring the getter, _set_<name> for declaring setter, see the part Properties for info how to use them)
-Intelligent constructing (different ways for building clever inheritance trees)
-Util functions that I usually need and I copy-paste them lots of times (string.split, table.contains, table.deepContains, table.merge)
-Fastclasses = a different, non-metatable, better performance class implementation

How to use it = Tutorial

Classes
SpoilerSimple usage

--declare class:
a = class {
  i = 2; --public fields begin with letter
  _x = 4; --private fields begin with underscore
  show = function(this) --functions can be private and public, too
	print(this.i)
	print(this.o)
	print(this._x) -- here you can access private vars because it's inside the class
  end;
}
--you can actually use the class itself, because the class is an instance itself
a.o = 4 -- you can add extra fields later, but only public
a._x = 5 --this will actually not change anything, my small library will ignore it
a.show() -- will print 2 2 4
-- create a clone (instance)
b = a()
b.show() -- will show 2 2 4
b.i = 7 -- will set b's i to 7, but not a's because b is (almost) independent now
print(b.i) -- output is 7
b.show() -- output is 7 2 4
a.show() -- output is 2 2 4

Method overriding:

a = class {
  _privatefunc = function(this)
	print("hi there from privatefunc from a")
  end;
  show = function(this)
	this._privatefunc()
	print("hi from show from a")
  end;
}
b = a { --extend a
  show = function(this)
	print("hi there from show from b")
  end;
}
b.show() --output: hi there from show from b
c = class( --different way of extending
{
  _privatefunc = function(this)
	print("hi there from privatefunc from c")
  end;
}, a)
c.show() --output: hi there from privatefunc from c hi from show from a
--as you can see everything is virtual by default, like in Java
--reminder:
c._privatefunc() -- of course this is attempt to call nil outside the class declaration

Properties:

a = class {
  _i = 2;
  show = function(this)
	print(this.i)
  end;
  _get_i = function(this)
	print("i was requested")
	return this._i
  end;
  _set_i = function(this,value)
	print("i will be "..tostring(value))
	this._i = value
  end;
}
a.i = 3 --output: i will be 3
a.show() --output i was requested 3
Extra knowledge that you will need (maybe):
- You can replace the getter with any non-function value, too, that results in a read-only field (from outside)
- You need to call functions with '.' - NOW EVERYWHERE - and declare them with extra "this" parameter (must be first)
- Every returned class (where you can't use private fields) has a field called "class", where you can use private methods and a field called "super", which contains all the superclasses (warning: if you create a class like this: ac {…} (ac = a parent class) the number 1 parent class is everything in the brackets, the number 2 is the class 'ac')

Fastclasses
SpoilerExample says everything:
f = fastclass {
  private = {
	l = function(this)
	  return this.public.i()
	end;
	i = 7;
  };
  public = {
	l = function(this)
	  print(this.private.l())
	end;
	i = function(this)
	  return this.private.i + this.public.a
	end;
	a = 5;
  };
}
f.l() -- output 12

Note: inheritance doesn't work with fastclasses yet :(/>/>
You can use table.merge for every private and every public and THEN use them for making a fastclass
Changelog
SpoilerI am not sure if anybody will be intrested enough in this that he'll remember version names so I'll not use them
2016 march:
26th
Added fastclasses
Now in classes you have to call methods with '.'
You can use properties inside classes with the same syntax as outside
25th
Original release

//Util function documentation: TODO

Download: http://pastebin.com/KVW9bYh5
pastebin get KVW9bYh5class

Edit: sorry for short var names I wrote this on android and tested it in QLua
Edited on 27 March 2016 - 06:43 AM
aDevilInMe #2
Posted 26 March 2016 - 09:34 AM
Hi Konlab, would you kindly consider using another name for this library as it is the name of a library I have maintained for ten years. Thanks.

https://oolua.org
Konlab #3
Posted 27 March 2016 - 08:42 AM
Hi Konlab, would you kindly consider using another name for this library as it is the name of a library I have maintained for ten years. Thanks.

https://oolua.org
Ok of course, sorry
aDevilInMe #4
Posted 27 March 2016 - 01:16 PM
Thank you, it is much appreciated.
Elttob #5
Posted 26 June 2016 - 10:10 AM
I like it a lot! Just what I was looking for :P/>
Wilma456 #6
Posted 26 June 2016 - 01:25 PM
I have a error, when I run this code:

os.loadAPI("/lib/class")
t = class {
a = 1
}
b = t()
print(b.a)
It just says "atttemp to call table"
Konlab #7
Posted 28 June 2016 - 03:26 PM
I have a error, when I run this code:

os.loadAPI("/lib/class")
t = class {
a = 1
}
b = t()
print(b.a)
It just says "atttemp to call table"
you loaded with os loadAPI
Load with dofile or use class.class

I like it a lot! Just what I was looking for :P/>/>
thanks! :D/>
moomoomoo3O9 #8
Posted 15 August 2016 - 03:41 PM
Quick recommendation, in the first metatable's __index method, you automatically pass this/self to any function. If you wanted to allow for either the . or : operator to be used, just put an if like so:

if type(v) == "function" then
  if (...) ~= inner then -- checks only the first argument because Lua automatically drops the rest
	return function(...)
	  tbl[k](inner, ...) -- call function with unblocked, original table
	end
  else
	return function(...)
	  tbl[k](...) -- call function with unblocked, original table
	end
  end
end
Edit: changed a == to a ~=
Edited on 18 October 2016 - 02:00 AM