Hello. With Java 8 came a new and useful feature for interfaces - default methods. For those of you who don’t know, this is what they look like:
public interface Test {
default void test() {
System.out.println("Testing");
}
}
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:
public interface Collidable{
public int getXPixel();
public int getYPixel();
public Hitbox getHitbox();
default void renderHitbox() {
renderHitbox(0xFF0C00);
}
default void renderHitbox(int color) {
Hitbox hitbox = getHitbox();
int xPixel = getXPixel();
int yPixel = getYPixel();
Game.getRenderEngine().renderSquare(color, xPixel + hitbox.getXStart(), yPixel + hitbox.getYStart(), hitbox.getWidthPixels(), hitbox.getHeightPixels());
}
/**
* Called in the <tt>addToLevel</tt> method of the object
*/
default void addCollidable() {
Game.getLevel().addCollidable(this);
}
/**
* Called in the <tt>removeFromLevel</tt> method of the object
*/
default void removeCollidable() {
Game.getLevel().removeCollidable(this);
}
/**
* Call in <tt>MovingObject.onMove</tt>. Necessary for the proper storage of this object in certain data structures
*/
default void updatePosition() {
Game.getLevel().updateCollidable(this);
}
}
This would then be implemented, along with other interfaces, in a class such as this:
public abstract class MovingObject extends LevelObject implements Updateable, Collidable {
public static final int AIR_DRAG = 4;
public static final int MAX_SPEED = 20;
private int xVel, yVel, dir;
protected MovingObject(int xPixel, int yPixel) {
super(xPixel, yPixel);
}
@Override
public void update() {
move();
}
@Override
public void addToLevel() {
addUpdateable();
addCollidable();
}
@Override
public void removeFromLevel() {
removeUpdateable();
removeCollidable();
}
protected void onMove(int pXPixel, int pYPixel) {
updatePosition();
}
protected boolean getCollision(int moveX, int moveY) {
return false;
}
protected void move() {
//move...
}
public void addVel(int xVel, int yVel) {
//add velocity...
}
}
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.
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.