This is the most awesome thing that has ever been created in the history of forever for LOVE.
Man, this makes things so much easier! In my game I was implementing my own minimal class system per-class (basically writing the :new function multiple times). The sub-classing, packages, and everything have made my game development so much faster!
I was going to try out PASSION, but it is listed as pre-alpha quality on the forum, so I'm currently avoiding it, but when it is finished I'll try to integrate it into my game!
middleclass & extras: middleclass 3.0 is out!
Re: MiddleClass & MindState: Object Orientation for LUA
Have you considered adding Interfaces as a capability?
For those who don't know what those are: Interfaces are objects that define what classes inheriting it must implement. Think of it as a class that prints errors if not all of it's functions are reimplemented.
For those who don't know what those are: Interfaces are objects that define what classes inheriting it must implement. Think of it as a class that prints errors if not all of it's functions are reimplemented.
Good bye.
- kikito
- Inner party member
- Posts: 3153
- Joined: Sat Oct 03, 2009 5:22 pm
- Location: Madrid, Spain
- Contact:
Re: MiddleClass & MindState: Object Orientation for LUA
Hi there!
I'm glad you liked MiddleClass & MindState.
I have thought about interfaces ... but I didn't have a place for them in Lua!
In my head, interfaces make more sense on closed-structure languages such as C++ or Java. Open-structured languages, such as Lua or Ruby, don't need them so much, since structures are not "closed" - for example, you can add methods to a class any moment you want, not just when creating it.
Mixins make more sense. They are not just "declarations of methods that a class must implement" ... they also have implementation (which the class can then modify). My implementation of mixins is a bit crude (just copy the methods to the class definition, not do much more) but effective.
You can simulate (partially) interfaces by creating a mixing like this:
I said "partially" because this will only raise an error if you execute MyClass.foo or MyClass.bar. On C++/Java, you will get the error sooner, on the compilation phase. This is a consequence of the fact that Lua structures are open.
I hope this all makes sense.
Just a note: I'll be making an update to MiddleClass soon, separatin the getterSetter stuff to a module (it's already done on the PÄSSION source)
Regards!
EDIT: Oh, and PÄSSION is more like alpha now. Ass soon as I finish the documentation, it can be considered Beta.
I'm glad you liked MiddleClass & MindState.
I have thought about interfaces ... but I didn't have a place for them in Lua!
In my head, interfaces make more sense on closed-structure languages such as C++ or Java. Open-structured languages, such as Lua or Ruby, don't need them so much, since structures are not "closed" - for example, you can add methods to a class any moment you want, not just when creating it.
Mixins make more sense. They are not just "declarations of methods that a class must implement" ... they also have implementation (which the class can then modify). My implementation of mixins is a bit crude (just copy the methods to the class definition, not do much more) but effective.
You can simulate (partially) interfaces by creating a mixing like this:
Code: Select all
MyInterface = {
foo = function(x,y)
error("You must implement your own version of foo in your class")
end,
bar = function(w,h)
error("You must implement your own version of bar in your class")
end
}
MyClass = class('MyClass')
MyClass:includes(MyInterface)
I hope this all makes sense.
Just a note: I'll be making an update to MiddleClass soon, separatin the getterSetter stuff to a module (it's already done on the PÄSSION source)
Regards!
EDIT: Oh, and PÄSSION is more like alpha now. Ass soon as I finish the documentation, it can be considered Beta.
When I write def I mean function.
- bartbes
- Sex machine
- Posts: 4946
- Joined: Fri Aug 29, 2008 10:35 am
- Location: The Netherlands
- Contact:
Re: MiddleClass & MindState: Object Orientation for LUA
Go does interfaces nicely, but the reason why it can do that is because it is a strongly typed language, without the 'almighty' lua tables, I would say that a correct implementation of interfaces in lua is (near) impossible.
- kikito
- Inner party member
- Posts: 3153
- Joined: Sat Oct 03, 2009 5:22 pm
- Location: Madrid, Spain
- Contact:
Re: MiddleClass & MindState: Object Orientation for LUA
Agreed. The fact that you can make additions to tables in runtime (even creating methods on the fly) kind of defeats the purpose of interfaces, which is to stablish a "contract" on compile time.
When I write def I mean function.
- kikito
- Inner party member
- Posts: 3153
- Joined: Sat Oct 03, 2009 5:22 pm
- Location: Madrid, Spain
- Contact:
Re: MiddleClass & MindState: Object Orientation for LUA
I've been doing some intense work lately on MiddleClass & MindState.
I use them extensively on PÄSSION; it has reached a point where every little change that I make in any of them can unadvertely "break" other parts. My approach until recently had been "trying the most complex game I have, and see if it works".
But that is tiresome and slow; I've decided to adopt the Test-Driven Phylosophy and wrote a bunch of tests. This is much more systematic than just "running the game and see if something breaks up" and it is also faster - in execution and in bug location, since you see exactly what fails.
MiddleClass' tests, as well as its associated methods (subclassOf, instanceOf, includes, class) has been fully tested and it is quite stable now. MindState is 80% tested.
TDD has helped me track down around 10 bugs; they were mostly edge cases and should not affect most people, but a couple were important enough to mention:
I use them extensively on PÄSSION; it has reached a point where every little change that I make in any of them can unadvertely "break" other parts. My approach until recently had been "trying the most complex game I have, and see if it works".
But that is tiresome and slow; I've decided to adopt the Test-Driven Phylosophy and wrote a bunch of tests. This is much more systematic than just "running the game and see if something breaks up" and it is also faster - in execution and in bug location, since you see exactly what fails.
MiddleClass' tests, as well as its associated methods (subclassOf, instanceOf, includes, class) has been fully tested and it is quite stable now. MindState is 80% tested.
TDD has helped me track down around 10 bugs; they were mostly edge cases and should not affect most people, but a couple were important enough to mention:
- MiddleClass didn't properly handle metamethods before. Now you can create classes with methods called __add, __mult etc and they will work correctly (they will even be inherited by subclasses, which was surprisingly tricky)
- MindState's popState method has been nearly completely rewritten; it had several bugs on it, mainly related with calling the right callbacks and popping states by name(that didn't work before)
When I write def I mean function.
- kikito
- Inner party member
- Posts: 3153
- Joined: Sat Oct 03, 2009 5:22 pm
- Location: Madrid, Spain
- Contact:
Re: MiddleClass & MindState: Object Orientation for LUA
I've completed the tests on MindState, and decided to simplify it a bit - I removed an esoteric feature that no one would ever use - states with parameters. Now the states must have an empty constructor, which is the default case and what 100% of the people need anyway.
I'll now proceed to add some mixins to the middleClass lib. These will be completely optional, so they will probably go on an "extra" or "plugins" folder. I still have to decide the name. I might put MindState inside that "extra" folder too.
Regards!
I'll now proceed to add some mixins to the middleClass lib. These will be completely optional, so they will probably go on an "extra" or "plugins" folder. I still have to decide the name. I might put MindState inside that "extra" folder too.
Regards!
When I write def I mean function.
-
- Party member
- Posts: 215
- Joined: Sun Jan 18, 2009 8:03 pm
Re: MiddleClass & MindState: Object Orientation for LUA
Haha, would be great to see test-driven programming take in LÖVE. How would you handle physics though?
I've been using Pässion for a toy project. I made a number of changes that I deemed necessary but none to the OOP folder, so I'm happy .
Hm, I dont understand this. Is the constructor somehow causing you problems because it seems strange to remove potentially useful functionality that comes for free. I can think of several possible uses, e.g. you have a state for when a button fades from one color to another and you specify the target color upon entering the state. Sure, there are other ways to do it but if has this approach to implement it (i.e. with a state) then the natural thing to do is to pass the color to the constructor.states with parameters. Now the states must have an empty constructor, which is the default case and what 100% of the people need anyway.
I've been using Pässion for a toy project. I made a number of changes that I deemed necessary but none to the OOP folder, so I'm happy .
If I haven't written anything else, you may assume that my work is released under the LPC License - the LÖVE Community. See http://love2d.org/wiki/index.php?title=LPC_License.
- kikito
- Inner party member
- Posts: 3153
- Joined: Sat Oct 03, 2009 5:22 pm
- Location: Madrid, Spain
- Contact:
Re: MiddleClass & MindState: Object Orientation for LUA
Hi Osuf,
I thought like you until I started actually programming the test for that functionality. It is actually very subtle. There are two factors that I need to explain:
1. States need two superclasses
States are classes, with a single modification: super works a bit differently on them - it first looks for methods on the current state's ancestors (just like a regular method does), but when that fails it still has the non-stateful methods to look over. Here's the shortest example I could think of:
I hope this is straightforward enough.
The consequence of all this is that States need 2 superclasses. One is their "Natural" superclass (where super looks first) and then there's the "Non-state" superclass. That's why State.subclass takes 3 parameters instead of two.
The base class is need is subtle: on a stateful method, super works differently than on regular methods. It will look "up" on the state ancestors first, but if
2. referencing the state instance is not possible
That's the other thing - self. It points to the StatefulClass instance (b on the previous example). It never points to the "state instance" in question.
With all this in mind, I concluded that controlling the state instances isn't something the MindState user is expected to do.
Nothing of the above is set in stone, though. I'm always open to new arguments on this.
By the way, you seem to be the only PÄSSION user for the moment. I'd be glad to review those changes you mention.
I thought like you until I started actually programming the test for that functionality. It is actually very subtle. There are two factors that I need to explain:
1. States need two superclasses
States are classes, with a single modification: super works a bit differently on them - it first looks for methods on the current state's ancestors (just like a regular method does), but when that fails it still has the non-stateful methods to look over. Here's the shortest example I could think of:
Code: Select all
local A = class('A', StatefulObject)
function A:foo() return 'A.foo' end
function A:bar() return 'A.bar' end
local AState = A:addState('State')
function A:foo() return 'AState.foo' end
local B = class('B', A)
local BState = B.states.State
function BState:foo() return super.foo() .. ' from BState' end
function BState:bar() return super.bar() .. ' from BState' end
local b = B:new()
b:gotoState('State')
print(b:foo()) -- AState.foo from BState
print(b:bar()) -- A.bar from BState
The consequence of all this is that States need 2 superclasses. One is their "Natural" superclass (where super looks first) and then there's the "Non-state" superclass. That's why State.subclass takes 3 parameters instead of two.
The base class is need is subtle: on a stateful method, super works differently than on regular methods. It will look "up" on the state ancestors first, but if
2. referencing the state instance is not possible
That's the other thing - self. It points to the StatefulClass instance (b on the previous example). It never points to the "state instance" in question.
With all this in mind, I concluded that controlling the state instances isn't something the MindState user is expected to do.
Nothing of the above is set in stone, though. I'm always open to new arguments on this.
By the way, you seem to be the only PÄSSION user for the moment. I'd be glad to review those changes you mention.
When I write def I mean function.
- kikito
- Inner party member
- Posts: 3153
- Joined: Sat Oct 03, 2009 5:22 pm
- Location: Madrid, Spain
- Contact:
Re: MiddleClass & MindState: Object Orientation for LUA
I've commited the latest changes on middleclass to github. The last change contains a not-yet-working version of the Callbacks module. I'm afraid I could not make it work on time before my holidays. I'll do my best to update it after I return. The rest of the code seems to do very nicely, I'm proud to say.
I'll go on holidays now and will not be able to answer questions here until mid-september. I doubt I'll do any forum reading during the next month, but you may try sending me a private message - I might get to read my email more often than the forum.
Regards!
I'll go on holidays now and will not be able to answer questions here until mid-september. I doubt I'll do any forum reading during the next month, but you may try sending me a private message - I might get to read my email more often than the forum.
Regards!
When I write def I mean function.
Who is online
Users browsing this forum: No registered users and 9 guests