5 ms·
Inheritance as taught in OO courses (deep class hierarchies) is bad most of the time. We can save 100 lines of code there by coupling 2 slightly related things
by ajuc 12y ago
Inheritance as taught in OO courses (deep class hierarchies) is bad most of the time.
We can save 100 lines of code there by coupling 2 slightly related things forever (and arbitrarily choosing this criteria for division as the most important).
I've made game before I knew OO programming. I haven't knew it then, but I used Interpreter Pattern - there was data model, with a list of records, each record had some enums deciding how game logic should handle it. There was main loop updating the model using these enums to choose logic to run on this record.
It wasn't pretty but it worked, I was able to modify it however I wanted, to choose logic to run on some record basing on enums, other atributes of given record, attributes of parent records, or of colliding records, on whatever I wanted basicaly.
Then I rewrote the game to use OO design (I was enthusiastic- this is exactly what I need - I thought). It turns out that I had to choose arbitrary divisions. I can divide game objects into Solid and non-solid, Static and Movable, Visible and Invisible, and also Smart vs Dumb Objects. Which division should be first in class hierarchy? All the rest would need to be duplicated anyway. SmartMovableVisible, SmartMovableInvisible, SmartStaticVisible, etc... Ugly.
Inheritance solves part of the problem and leaves you with inconsistent solution.
The real solution is strategy pattern, and composition over inheritance. It can be done just as well in languages without inheritance (but with lambdas).
- vegedor 12y agoI don't agree with the premises. Teaching in higher classes assumes independent study of the reader as enhancement. For me it's making much more sense to look at a consistent implementation of OOP features in C [1] (understanding less and less to the end of the latest paper). It make sense to understand the data structures behind it to reason about the transformation of your game to OOP. For your problem there's Multiple Inheritance, but not every OOP-Language supports it. You have movable, visible, etc as objects and game_objects inherit from them as needed. If you have learned OOP with a toy metaphor and dived straight into Java or Python, you might miss out on some formal fundamentals. Some say Java doesn't implement OOP properly, but at least it's running ;). Naturally most students also want to get practical and don't want to dabble in the dire theory. In C you'd have bitmasks encoding the types and functions called based on that (or how'd you do it? gibe references). If you had your logic wired up to call functions straight away, it might have made sense to encode the functionality as member functions, to have an object being immobile simply by not using the move function. The data would be stored in pools of other objects, like location data, that your functions work on. I'm still learning. If I'm not making sense, tell me, but I think that's what MV* does? For a simple enough problem there are different probable solutions [1] http://ldeniau.web.cern.ch/ldeniau/oopc.html http://ldeniau.web.cern.ch/ldeniau/oopc.html but there are others as well
- ajuc 12y ago@vegedor you are hellbaned I think. I can't respond to you and your post is grey. I wrote the OO game in C++, but I avoided multiple inheritance, because there were warnings everywhere: "don't use multiple inheritance". And I don't think it would be much help in the end. Another thing inheritance doesn't solve - when you want to choose which logic should run on your "object" depending on dynamic conditions. For example I had ParticleEffect abstract class, Smoke and Fire derived from it. Fire reacted differently to collisions with stuff, than smoke. Fire partices were smaller with each frame to simulate flames, smoke was getting bigger and more transparent with each frame to simulate, well, smoke. Then I wanted to make fire that turns into smoke after a couple of frames. Solution 1 - merge both classes, make enum field inside, switch it after a couple of frames [not OO design - behaviour depends on fields not on classes] Solution 2 - destroy fire object after a couple of frames and create new smoke object in its place [unnessesary allocation and deallocation is bad in games, also this complicates identity - for fire and smoke it doesn't matter, but for player and bullets it's important - I need to ensure player isn't hit by bullets he shoot, that's achieved by keeping "parent" pointer in each object, when the player is recreated because he got new behaviour - all the pointers are wrong and need to be updated]. I can't change class of object dynamicaly, so all the OO divisions are static in time, I have to workaround class hierarchy to model my problem correctly. Another thing - in collision detection, the logic to run should depend on both colliding objects types, and some of their fields. With OO I have to workaround this again (because most OO languages are single-dispatch). Another thing - OO data is much harder to serialize. Structural data allows banal serialization. This is solved in some languages (like Python or Java) by providing serialization in the core language, but in C++ or javascript serializing arbitrary object graph correctly is nontrivial. Serializing list of records was trivial even in Turbo Pascal ;)