Simply put, they allow for methods in interfaces that are not static (i.e. that are inheritable) to write code. I have been using this to make something akin to the Component pattern, meaning each game object is made up of multiple unrelated parts and they all come together in such a way that, with some code in the actual object, they form a complete entity.Here is an example:

I have found this extremely helpful in my code. Tell me what you think of it and see if you can use it!EDIT - however, funnily, I forgot to mention the largest and most obvious disadvantage about this - you cannot store instance variables. You can do what I did in Collidable and just force them to implement methods, but this is not always optimal.

To summarize, you believe default methods are useful because they allow you to essentially extend the functionality of more than one class.

To extend the discussion...

For clarity, extending refers extending an abstract class while extension refers to extending or implementing functionality from default methods.

While extending multiple classes is mostly a technical restriction, it is not a bad one. Extension inherently creates complexity, making your code more difficult, even if only a little, to understand. Most people do not know about them and even if they did, a good programmer wants to make their code as simple as possible. Use default methods only if you must.

Regarding your code...

I seem like you want to be able to use the interface and not have to keep adding that line of code. This is a definitely a composition over inheritance problem. One of the issues with approach is that it does not scale well. You will end a bunch of classes or game entities, each only different by the interfaces. Unless you are making a very very small game, this will become very difficult to manage. I am sure there are more issues but I am no OOP guru.

The composition approach is to create one class, particularly one that implements Collidable and decide whether it is collides based on the data and not the its definition. For example, you could have some with a normal hitbox and some with an empty hitbox.

I would disagree with your thought that it brings unnecessary complexity in the form of multiple different classes that are variations of each other just with different interfaces. The reason I came up with this was to fix the following problem with my Block hierarchy. I wanted 3 types of blocks - Producer, Consumer, and Function (combination of producer and consumer), each of which is self-explanatory. However, I cannot have Function be a child of both classes, of course, so that would mean I would have to rewrite code from both of them which has the added problem of not being able to store the Function block as a Producer or a Consumer. However, with this method, I can do that:

1 2

ProducerBlockp = newFunctionBlock(); // EDIT - I'd just like to point out that this is only an example and I will not have for some reason a concrete class called FunctionBlock :DConsumerBlockc = newFunctionBlock();

There are limitations, but provided that both Producer and Consumer have what is necessary and nothing more and I run what is necessary and nothing more on them, it works well.In my codebase, this is a very handy thing for keeping storage of objects manageable and reasonable. Also, you said:

Quote

The composition approach is to create one class, particularly one that implements Collidable and decide whether it is collides based on the data and not the its definition. For example, you could have some with a normal hitbox and some with an empty hitbox.

I had this before - simply a Hitbox instance called Hitbox.NONE. However, this approach removes the need for checking this every time we want to do certain operations.

Basically, I find it more cumbersome to have one high level class with tons and tons of methods that are barely used by many children. There are of course other solutions to this, but this method allows for them to actually be an instance of some form of the functionality which is something that outweighs, for example, having some sort of MouseActionDetector with a bunch of anonymous inner class methods if I wanted to have a Block run code when you click on it.

I really do appreciate your thoughts though as of course I cannot predict what will result of this, but from the points you made, I still think it works well.

I would disagree with your thought that it brings unnecessary complexity in the form of multiple different classes that are variations of each other just with different interfaces. The reason I came up with this was to fix the following problem with my Block hierarchy. I wanted 3 types of blocks - Producer, Consumer, and Function (combination of producer and consumer), each of which is self-explanatory. However, I cannot have Function be a child of both classes, of course, so that would mean I would have to rewrite code from both of them which has the added problem of not being able to store the Function block as a Producer or a Consumer. However, with this method, I can do that:

1 2

ProducerBlockp = newFunctionBlock(); // EDIT - I'd just like to point out that this is only an example and I will not have for some reason a concrete class called FunctionBlock :DConsumerBlockc = newFunctionBlock();

There are limitations, but provided that both Producer and Consumer have what is necessary and nothing more and I run what is necessary and nothing more on them, it works well.

I guess this is an example of default methods being useful. But in practice, I cannot imagine there being many examples as obvious as this. But then again, I am only one person.

Basically, I find it more cumbersome to have one high level class with tons and tons of methods that are barely used by many children. There are of course other solutions to this, but this method allows for them to actually be an instance of some form of the functionality which is something that outweighs, for example, having some sort of MouseActionDetector with a bunch of anonymous inner class methods if I wanted to have a Block run code when you click on it.

If the class looks cluttered, then hide details in new fields.If you are worried about a bunch code that is not being used, then STOP because optimizing your code early leads to complex-overengineered systems.If things are still looking that bad and cluttered, then add another high level class. You are not forced to use only one class in composition.

What is most important is creating a system that simple and natural. If 30 classes that are different only through inheritance is more natural than 4 or 5 that are data driven, then feel free.

That's what everyone feared people will use default methods for There are concepts like traits or mixins, which (I think) go in the same direction as what you are targeting.... you want to have multiple inheritance (of implementation). Why inheritance? Because that's what we OO people use to reuse implementations. Why? Becuase it is so damn easy to use, from a very shortsighted perspective. But multiple inheritance is something you should avoid, and the magic words have already been said: Composition over inheritance.

There's (usually) nothing wrong with using multiple (interface) inheritance... but you want (default) implementations, if many (interface) implementations share (almost) the same logic. Kotlin tackles this problem whith making composition as easy as (implementation) inheritance by adding delegation as a first-class citizen to the language. Example: https://kotlinlang.org/docs/reference/delegation.html . Scala is even a bit more crazy and allows for stateful traits - interfaces with implementations and fields and so on.

Funny, I experimented with default methods to have a more comfortable implementation of Transformations in my engine... I didn't want to put Transform ontop of my hierarchy, so I added an Interface Transformable. This is implemented by Transform and provides a method getTransform. All methods, like getPosition etc. are default implemented and call an abstract getTransform method... the concrete Implementation (Transform) implements Transformable and overrides the default methods... so every class can implement Transformable, implement the abstract getTransform method with returning a field and voila, you're done, no (implementation) inheritance and everything can easily be a Transform But I ditched it. Felt ugly somehow.

Interfaces are a useful concept, not least because it is simple. Simple is good. Which is no longer true for interface default methods. The reason they were added was to be able to add the streaming stuff to collections classes. Alright, what we got is the ugly little brother of abstract classes.There is another issue with your design: the probably unnecessary dependency from Collidable to the game and level classes. Minimizing dependencies is very important for developing maintainable software.

Lethal Running - a RPG about a deadly game show held in a futuristic dystopian society.

There is another issue with your design: the probably unnecessary dependency from Collidable to the game and level classes. Minimizing dependencies is very important for developing maintainable software.

In layman terns, have your Level add Collidables and not Collidables add themselves to the level. Makes a lot of sense because Collidables or the things are collidable exist INSIDE your level.

I cannot stress how important it is to think SIMPLY and not use over-complicated solutions.

Hmmm. Well I had that before, I had methods that the level used to add, for instance, DroppedItem objects to itself, and it would return if it was successful. However, I couldn't figure out a way that I felt was good for other objects.

Hmmm. Well I had that before, I had methods that the level used to add, for instance, DroppedItem objects to itself, and it would return if it was successful. However, I couldn't figure out a way that I felt was good for other objects.

Just have one method for add the general entity. i.e. addEntity(Entity entity);

All your Level class really has to do is update entities. If each your entities each have all possible data (hitbox, graphics, etc) then you can handle things like collision and rendering without knowing the subclass.

Just have one method for add the general entity. i.e. addEntity(Entity entity);

All your Level class really has to do is update entities. If each your entities each have all possible data (hitbox, graphics, etc) then you can handle things like collision and rendering without knowing the subclass.

What I had originally was the latter. Just a bunch of different methods for each object. Then I switched to a single one with a bunch of instanceof and if/else statements, but I just thought that that was so clumsy and there had to be some way to make use of Java's hierarchy. So I added a method in the top level class, addToLevel, which would go directly into the level objects and add it. I realize that it means it's not separate from the level, true, but it meant that I could override it in child classes. It seemed so much more natural and clean.

EDIT - and also, for this point

Quote

If each your entities each have all possible data (hitbox, graphics, etc) then you can handle things like collision and rendering without knowing the subclass.

the way I see it is I can go through every object, check if it needs rendering, collision, etc., or I can use the default methods for a Renderable or Collidable interface and be sure that the class actually needs what it's being checked for. I still don't need to know the subclass, all I need to know is given to me by the interface. I do see another disadvantage to that though - it means I have to store multiple lists, many of which may well contain the same object. However, as it's just a pointer, it shouldn't be too large of a negative effect.

What I had originally was the latter. Just a bunch of different methods for each object. Then I switched to a single one with a bunch of instanceof and if/else statements, but I just thought that that was so clumsy and there had to be some way to make use of Java's hierarchy. So I added a method in the top level class, addToLevel, which would go directly into the level objects and add it. I realize that it means it's not separate from the level, true, but it meant that I could override it in child classes. It seemed so much more natural and clean.

the way I see it is I can go through every object, check if it needs rendering, collision, etc., or I can use the default methods for a Renderable or Collidable interface and be sure that the class actually needs what it's being checked for. I still don't need to know the subclass, all I need to know is given to me by the interface. I do see another disadvantage to that though - it means I have to store multiple lists, many of which may well contain the same object. However, as it's just a pointer, it shouldn't be too large of a negative effect.

I'll make it simple for you. Is that optimization worth the cost in code quality. No matter what anyone says, both methods, and many other, are possible.

I personally value code quality, particularly less classes, less static code, less lines of code, and more encapsulation. Would it not be amazing if your "core" engine was heavily data-driven and just 30-40 classes with the actual data being in arbitrary files. I am also willing to sacrifice speed because speed really does not matter most of the time.

java-gaming.org is not responsible for the content posted by its members, including references to external websites,
and other references that may or may not have a relation with our primarily
gaming and game production oriented community.
inquiries and complaints can be sent via email to the info‑account of the
company managing the website of java‑gaming.org