0
LWCF - my take on component oriented programming
On my path of making a GUI toolkit, I thought Component Oriented Programming would suit best for such task, because GUIs are essentially made of little blocks that do their own thing. Inheritance and Object Orientation, while usable, creates a mess for me. So what I came up with was an extremely (no kidding) minimal component framework. While it is only a handful of actual code lines, funnily enough took me hours to get right. I call it the Light-weight Component Framework. In the process of explaining how it works, I will create a Player with a Movement component, that will be attached to Player, giving it "legs"!
3 Réponses
+ 1
2/3
- the Receiver component -
Now comes the fun part, messaging between the components. Since components are very lonely we need a way for them to communicate.
Every component has an event() method, which will send out the given messages to all its children. The basic usage is:
component.event(message=data)
To demonstrate, we shall add a move(x, y) function to our player class, which will send out a message when it's called.
class Movement(Component): pass
class Player(Component):
def move(self, x, y):
print('I AM MOVING!')
self.event(move=(x,y))
player = Player()
player << Movement()
player.move(1,1)
Running this code will just make the player scream, and nothing else will happen.
The Receiver Component lets child components receive the parent's messages. The Receiver will register a certain keyword and it will call the function it's given with the data it got from the message.
This is how we do it:
component << Receiver('message', function_callback)
We can attach it now:
class MyComp(Component):
def __setup__(self):
self << Receiver('message', function)
Or later:
class MyComp(Component): pass
MyComp() << Receiver('message', function)
+ 1
1/3
- the Component class -
All component classes must inherit this to become a part of the bigger picture. And that's the only inheritance you will need to do on your path to modularity.
To make it cleaner I had to forbid the use of __init__(). While it might seem silly, because the only thing the Component initializer does is create a list, I'd hate to type super().__init__() at the beginning of each of my components __init__ function.
Instead __init__ is replaced by __setup__, and acts just like __init__, so no changes besides a little different name to use.
Components can be attached to eachother in a couple ways.
First way is using the .attach() method each component has. It can be used to attach lots of components at once.
component.attach(another_component, yet_another, ...)
Second way is using the overloaded left-shift bitwise operator (what a moutful, maybe "two birds flying West"?) This can only take one Component though.
component << another_component
So let's make Movement and Player components (yes, the player itself can be used as a component). Then we will attach Movement to Player.
class Movement(Component): pass
class Player(Component): pass
player = Player()
player << Movement()
Simple, right?
0
3/3
So lastly let's give our player the legs it deserves
class Movement(Component):
def __setup__(self):
self.pos = [0,0]
self << Receiver('move', self.move)
def move(self, x, y):
self.pos[0] += x
self.pos[1] += y
print('Movement: moved by', x, ';', y, 'to', self.pos)
class Player(Component):
def move(self, x, y):
print('Player: I AM MOVING!')
self.event(move=(x, y))
player = Player()
player << Movement()
player.move(-1,-1)
Output:
Player: I AM MOVING!
Movement: moved by -1 ; -1 to [-1, -1]
It's so simple, so primitive, yet so effective. It's probably not that cool as I think it is :D
The module along with this very example can be found on my profile or here: https://code.sololearn.com/cE8LdVeB58F3