Currently, I'm migrating a game from Python to Java. In it, I created a Generator that returns a "class" that will be created with arguments its caller would have, like so:
package me.mathmaniac.smallworlds.world.generation;
import me.mathmaniac.smallworlds.block.Block;
import me.mathmaniac.smallworlds.block.NullBlock;
import me.mathmaniac.smallworlds.world.LayerType;
public class FlatGenerator implements Generator {
#Override
public Block generateBlock(LayerType ltype, int x, int y) {
switch (ltype) {
case Liquid:
return HoleBlock;
case Solid:
return GrassBlock;
case Air:
return AirBlock;
default:
throw new RuntimeException();
}
}
}
Called from here:
package me.mathmaniac.smallworlds.world;
import me.mathmaniac.smallworlds.block.Block;
import me.mathmaniac.smallworlds.world.generation.Generator;
public class World {
Generator generator = ...;
// ...
private void generateBlocks(int x, int y) {
for (LayerType ltype : LayerType.values())
setblock(generator.generateBlock(ltype, x, y).new(x, y, ltype), //.new() is as an example
x, y, ltype);
}
}
How would I accomplish this in Java?
You want to use the Factory Pattern
You would have a few classes: an abstract class Block (or an interface) and the factory class BlockFactory (or as you called it, FlatGenerator).
If there are a number of functions that can have the same implementation across all Block types, then make the base class Block be an abstract class and put those methods in there. Otherwise, you can use an interface.
One approach could be to give all your layer classes the same interface and a no-argument constructor, and return Class<T> object from the method that returns the class to be instantiated later:
interface Layer {
void init(LayerType ltype, int x, int y);
}
class Liquid implements Layer {
public Liquid() {
...
}
public void init(LayerType ltype, int x, int y) {
...
}
}
class Solid implements Layer {
public Solid() {
...
}
public void init(LayerType ltype, int x, int y) {
...
}
}
With this setup in place you could do this:
public Class generateBlock(LayerType ltype, int x, int y) {
if (...) return Liquid.class;
if (...) return Solid.class;
...
}
The caller would initialize the layer as follows:
Layer layer = (Layer)generator
.generateBlock(ltype, x, y)
.newInstance();
layer.init(ltype, x, y);
I would just do it in the traditional OOP style.
First define an interface for a factory class
public interface BlockFactory {
Block createInstance(int x, int y, LayerType ltype);
}
And then define corresponding factories
public class HoleBlockFactory implements BlockFactory {
public Block createInstance(int x, int y, LayerType ltype) {
return new HoleBlock(x, y);
}
}
public class GrassBlockFactory implements BlockFactory {
public Block createInstance(int x, int y, LayerType ltype) {
return new GrassBlock(x, y);
}
}
Finally in your generator first you get a factory in your switch statement and the use the factory to create objects when you need:
public class FlatGenerator implements Generator {
#Override
public BlockFactory generateBlock(LayerType ltype, int x, int y) {
switch (ltype) {
case Liquid:
return new HoleBlockFactory();
case Solid:
return new GrassBlockFactory();
default:
throw new RuntimeException();
}
}
}
}
public class World {
Generator generator = ...;
// ...
private void generateBlocks(int x, int y) {
for (LayerType ltype : LayerType.values())
setblock(generator.generateBlock(ltype, x, y).createInstance(x, y, ltype), //.new() is as an example
x, y, ltype);
}
}
Related
In my project I came across this problem, where I have an abstract class of Entity, and it's children are Player, Shot and Enemy. I want to check for collision between them. A separate Physics class is doing the collision evaluation with the following code:
public class Physics {
private static int height = 32;
private static int width = 32;
public static void collision(Entity entity, LinkedList<Entity> eList) {
for (int i = 0; i<eList.size(); i++) {
if (entity.getBounds(width, height).intersects(eList.get(i).getBounds(width, height))) {
entity.collidesWith(eList.get(i));
}
}
}
}
The linkedList contains both Shots and Enemies, and yet for some reason, the collision only calls the collidesWith(Entity entity) method, instead of the collidesWith(Shot b) or collidesWith(Enemy e).
edit: The mentioned classes (with only the code that I think would matter from them in this case)
Entity:
public abstract class Entity {
protected double x;
protected double y;
public Entity (double x, double y) {
this.x = x;
this.y = y;
}
public abstract void tick();
public double getX() { return x; }
public double getY() { return y; }
public Rectangle getBounds(int width, int height) {
return new Rectangle((int)x, (int)y, width, height);
}
public abstract void collidesWith(Entity e);
public abstract void collidesWith(Enemy e);
public abstract void collidesWith(Shot s);
Player:
public class Player extends Entity {
private boolean alive;
private int gameWidth, gameHeight;
private GameController gCont;
private Textures textures;
public Player( String name, int x, int y, int gameWidth, int gameHeight, Textures textures, GameController gCont) {
super(x,y);
this.name = name;
this.score = 0;
this.gameWidth = gameWidth;
this.gameHeight = gameHeight;
this.gCont = gCont;
this.textures = textures;
this.alive = true;
}
public void tick() {
gCont.collisionCheck(this);
}
public void collidesWith(Enemy e) {
System.out.println("Player collides with enemy");
this.alive = false;
}
public void collidesWith(Shot s) {
return;
}
public void collidesWith(Entity e) {
System.out.println("collided with entity");
return;
}
Shot
public class Shot extends Entity {
private Textures textures;
private GameController gCont;
public Shot(double x, double y, Textures textures, GameController gCont) {
super(x, y);
this.textures = textures;
this.gCont = gCont;
}
public void tick() {
x+=10;
gCont.collisionCheck(this);
}
public void collidesWith(Entity e) {
return;
}
public void collidesWith(Enemy e) {
gCont.removeEntity(e);
gCont.removeEntity(this);
gCont.addScore();
}
#Override
public void collidesWith(Shot s) {
return;
}
Enemy
public class Enemy extends Entity {
private int speed;
public Enemy(double x, double y) {
super(x, y);
Random random = new Random();
speed = random.nextInt(3)+1;
}
public void tick() {
x-=speed;
}
public void collidesWith(Entity e) {
return;
}
#Override
public void collidesWith(Enemy e) {
return;
}
#Override
public void collidesWith(Shot s) {
return;
}
How can I get it to call to the correct functions?
Look into Java's Generics. I think you could use something like this:
public abstract class Entity<T> {
protected double x;
protected double y;
public Entity (double x, double y) {
this.x = x;
this.y = y;
}
public abstract void tick();
public double getX() { return x; }
public double getY() { return y; }
public Rectangle getBounds(int width, int height) {
return new Rectangle((int)x, (int)y, width, height);
}
public abstract void collidesWith(T e);
}
Might be wrong, I am new to answering questions on stackoverflow.
Hope this gives you some clarity:
entity.collidesWith(eList.get(i));
eList.get(i) in that line, in your Physics class Entity returns an an object of type Entity.
This is because it is defined like that:
LinkedList<Entity> eList
That means that if you have an overload that takes that Entity it would just call that method. This is exactly what I see in your code. You have a method overload for "collidesWith" with Argument: Entity.
In all of the children classes of Entity.
I think you should read more about "Java Polymorphism".
For me the Entity class knowing about Enemy and Shot is wrong.
Why don't you remove these two methods from Entity and subclasses:
public abstract void collidesWith(Enemy e);
public abstract void collidesWith(Shot s);
And keep and implement only:
public abstract void collidesWith(Entity e);
If you need to know the type of Entity e passed as argument, you can use reflection, but this is bad design. It is better to implement collidesWith in such way that it doesn't need to know the exact type of the passed argument.
I think a solution other than Generic type as specified by Jamie Bisotti, is to use an interface and a switch to check which class is what.
This is the interface that declares a method that all entities that can collide must have:
public interface Collidable {
public boolean collidesWith(Collidable entity);
}
Then each class that you want to be able to collide has to implement that:
public class Enemy extends Entity implements Collidable {
private int speed;
public Enemy(double x, double y) {
super(x, y);
Random random = new Random();
speed = random.nextInt(3)+1;
}
public void tick() {
x-=speed;
}
#Override
public void collidesWith(Collidable e) {
if (e.getClass().equals(Shot.class)) {
// DO SOMETHING, I am colliding with a shot
} else if(e.getClass().equals(Enemy.class)) {
// I am colliding with an Enemy
}
. . . etc
}
I prefer to use Interfaces so I can specify each behaviour. At the moment it seems to be all simple and everything can be extended from the Entity abstract class, but there will be a moment when you will differentiate each entity by many other feature.
For example a flying enemy, a walking enemy, ecc ecc and you can specify each feature with an interface.
In this case, the interface is also very simple. But you could specify many methods that you want to be implemented such as
public boolean canCollide();
public boolean isAlive(); //if the entity is already dead you might want not to stop a bullet
public boolean isAnimatingDeath(); //if the entity is animating death could collide with another antity because of its exploding animation, maybe you want to avoid that.
You can implement som method in the abstract Entity class, but that abstract entity shouldn't know about its children. This is the reason to implement some methods using the generic "Collidable" type as input, directly in the children.
I have 2 enums which look similar:
public enum enum1{
A(1,1),
B(2,2);
private final int x,y;
enum1(int x,int y){
this.x=x;
this.y=y;
}
int func(){ return this.x+this.y; }
}
public enum enum2{
C(3,3),
D(4,4);
private final int x,y;
enum2(int x,int y){
this.x=x;
this.y=y;
}
int func(){ return this.x+this.y;}
}
public class test{
void method(enum1 e){ /*something using func*/ }
void method(enum2 e){ /*something using func*/ }
}
How do I abstract the functionality of these enums in an interface and use only one method in the test class instead of two by passing the interface.
Edit: I don't want the enums to be merged. I need separate enums.
One thing is for sure: as long as x and y are private and there's no way to read them from outside the class - you would have to implement the same method for each enum. If you allow the reasonable change to add accessors to these fields in the enums, then you can use an interface's default method to implement the umbrella behavior:
interface Addable {
int getX();
int getY();
default int add() {
return getX() + getY();
}
}
enum Enum1 implements Addable {
A(1, 1), B(2, 2);
private final int x, y;
Enum1(int x, int y) {
this.x = x;
this.y = y;
}
#Override
public int getX() {
return x;
}
#Override
public int getY() {
return y;
}
}
Then you can make a call like Enum1.B.add() which will give 4. As for your test class:
public class Test {
void method(Addable e) { e.add(); }
}
is now valid for anything that implements Addable.
If you're worried about bloating the code, I recommend using Lombok:
#RequiredArgsConstructor
enum Enum1 implements Addable {
A(1, 1), B(2, 2);
#Getter
private final int x, y;
}
Note: type names should start with an uppercase. enum1 and test shoud be Enum1 and Test.
Create an interface that is implemented by each enum, only 'problem' the method must be public:
public interface Inter {
public void func();
}
public enum Enum1 implements Inter {
A(1,1),
B(2,2);
private final int x,y;
Enum1(int x,int y) {
this.x=x;
this.y=y;
}
#Overwrite
public int func() { return this.x+this.y; }
}
public enum Enum2 implements Inter {
...
#Overwrite
public int func() { ... }
}
public class Test {
void method(Inter e) {
// something using func
int sum = e.func();
}
}
public abstract class SuperClass {
public int x, y;
public static int z;
}
I want every subclass of SuperClass to have the static variable z. Naturally z will contain a different value for each subclass. I'm hoping to avoid defining z in every subclass, since it's going to be a functional dependancy of values x and y; Is this possible?
Unlike instance variables that are "one per instance", static variables are not "one per subclass" - they are "one per declaring class". In other words, subclasses of SuperClass share SuperClass.z, but they cannot "override" it on a class-by-class basis.
It does not mean that you cannot implement it yourself: on way to make your own per-subclass storage of integers is adding a static Map<Class,int> zs to SuperClass, with optional functions for accessing the data:
public abstract class SuperClass {
public int x, y;
private static Map<Class,Integer> zs = new HashMap<Class,Integer>();
protected static int getZ(Class c) {
Integer res = zs.get(c);
return res == null ? -1 : res.intValue();
}
protected static void setZ(Class c, int v) {
zs.put(c, v);
}
}
class SubClassOne extends SuperClass {
public int getZ() {
return SuperClass.getZ(SubClassOne.class);
}
}
class SubClassTwo extends SuperClass {
public int getZ() {
return SuperClass.getZ(SubClassTwo.class);
}
}
Probably the best way to do this is to have a z() method or similar in the abstract class, and override the method in the subclasses you want.
Example:
public abstract class SuperClass {
public int x, y;
protected int z() {
return 42; // protected so only subclasses can see it - change if required
}
}
public class SubClassOne extends SuperClass {
public void foo() {
// do something...
int z = z();
// something else...
}
}
public class SubClassTwo extends SuperClass {
#Override
protected int z() {
return 1;
}
// use z() accordingly
}
if i understand you correctly then do
public abstract class SuperClass {
public int x, y, z;
public SuperClass(int z) {
this.z = z;
}
}
then any class that extends this class inherits z;
Im currently making a simple pluginable program. My problem is that I don't want to let plugin access all base-plugin fields/methods. For example:
public abstract class BasePlugin {
private int x; //Mysterious x
public abstract void update(); //update func that may need x, but can't change it
protected final int getX() {return x;} //x accessor
}
And that would work unless you realize that there is no way to set x.
What can I do? I want to make subclass (plugin) unable to change x, but let it read the value. Value should be accesible at least once when creating (that would be enough).
EDIT: Constructor works in most cases, but what if I have for example:
public abstract class BasePlugin {
private List<int> x; //Mysterious x
public abstract void update(); //update func that may need x, but can't change it
protected final List<int> getX() {return x;} //x accessor
public BasePlugin(List<int> y) {x = y;}
}
public class Plugin {
public Plugin(List<int> y)
{
super(y);
y.remove(0); //Will it work?
}
}
An abstract class is permitted to have a constructor, so you can create a parameterless constructor for BasePlugin:
public abstract class BasePlugin {
private int x; //Mysterious x
public BasePlugin() {
x = 42;
}
public abstract void update(); //update func that may need x, but can't change it
protected final int getX() {return x;} //x accessor
}
And now when a plugin is created, x is set to 42. You don't even need to make any code changes to the plugins to make them use this constructor.
To answer the edited question: If x is a List and you don't want the plugins to modify it, your constructor should be copying it and wrapping it in an unmodifiable list. Otherwise, any plugin can call getX().add(myObject).
public BasePlugin(List<int> y) {
List<int> temp = new ArrayList<int>();
Collections.copy(temp, y); // shallow copy of the list
this.x = Collections.unmodifiableList(temp);
}
Now if the plugin's constructor is
public Plugin(List<int> y)
{
super(y);
y.remove(0); //Will it work?
}
It will have no effect on the BasePlugin's list.
You can add a constructor to get your property initialized by the subclasses:
public abstract class BasePlugin {
private int x; //Mysterious x
public BasePlugin(int x) {
this.x = x;
}
public abstract void update(); //update func that may need x, but can't change it
protected final int getX() {return x;} //x accessor
}
You can use Constructor Injection.
public abstract class BasePlugin{
private int x;
public BasePlugin(int x){
this.x=x;
}
public abstract void update(); //update func that may need x, but can't change it
protected final int getX() {return x;} //x accessor
}
And in your childs
public class Plugin extends BasePlugin{
public Plugin(int x){
super(x);
}
}
suppose i have the following case Parent class, and two Child classes, each child add a new parameter to the parameters inherited from the parent. Example
public class Parent {
private int x;
public Parent(int x) {this.x = x;}
public int getX() {return x;}
public void setX(int x) {this.x = x;}
}
First child
public class FirstChild extends Parent {
private int y;
public FirstChild(int x, int y) {
super(x);
this.y = y;
}
public int getY() {
return y;
}
public void setY(int y) {
this.y = y;
}
}
Second child
public class SecondChild extends Parent{
private int z;
public SecondChild(int x, int z) {
super(x);
this.z = z;
}
public int getZ() {
return z;
}
public void setZ(int z) {
this.z = z;
}
}
so how can i use the factory method here?,
You cannot use "pure" factory or factory method patterns here. These patterns are good when you want to create instances of different subclasses of same base class (or interface) in case that the mechanism of creation the instances is similar. For example all class have constructor or factory method with the same prototype.
In this case you can use reflection or elipsis:
class MyFactory {
Parent createInstance(Class clazz, int ... args) {
if (FirstChild.class.equals(clazz)) {
return new FirstChild(args[0]);
}
if (SecondChild.class.equals(clazz)) {
return new SecondChild(args[0], args[1]);
}
throw new IllegalArgumentException(clazz.getName());
}
}
interface Factory {
Parent newParent();
}
class FirstFactory implements Factory {
Parent newParent() { return new FirstChild(); }
}
class SecondFactory implements Factory {
Parent newParent() { return new SecondChild(); }
}
class Client {
public void doSomething() {
Factory f = ...; // get the factory you need
Parent p = f.newParent();
use(p)
}
// or more appropriately
public void doSomethingElse(Factory f) {
Parent p = f.newParent();
use(p)
}
}
// Or...
abstract class Client {
public void doSomething() {
Factory f = getFactory();
Parent p = f.newParent();
use(p)
}
abstract Factory getFactory();
}
class FirstClient extends Client {
Factory getFactory() {
return new FirstFactory();
}
}
class SecondClient extends Client {
Factory getFactory() {
return new SecondFactory();
}
}
Or (probably fits better what you need) :
public class ChildrenFactory {
FirstChild newFistChild() { return new FirstChild(); }
SecondChild newSecondChild() { return new SecondChild(); }
// or
Parent newFistChild() { return new FirstChild(); }
Parent newSecondChild() { return new SecondChild(); }
}
Probably you don't really need to use the Parent interface.
You may have a factory class which generates either first child or second child as below
class Factory{
Parent createChild(String child) {
if(child.equals("first"))
return new FirstChild();
if(child.equals("second"))
return new SecondChild();
}
}
Also this link below will help you understand factory pattern better http://www.hiteshagrawal.com/java/factory-design-pattern-in-java