Multiple type custom arraylist - java

I currently am trying to make a simple RPG-ish game. I want monsters to spawn randomly on the map. I have it set up so that when I want one to spawn it is added to an ArrayList called monsters. I will be having many different types of monsters by the time I am done, and each one has its own class (ex. Zombie, Ghost...) each class will have a method to draw the monster called draw. I want to know how I can do this.
Monsters is an ArrayList<Object> so it will be able to have the different classes in it, but It won't let my do Monsters.get(i).draw(); Is this actually possible, or am I being stupid.

You failed to cast the object ArrayList<Object> back to Monster
// Monster.get(i) == Object
// (Monster) Monsters.get(i) == Monster
// cast the list item i from Object to Monster
((Monster) Monsters.get(i)).draw();
A better solution:
interface Monster {
void draw();
}
// implement draw on each
class Zombie implements Monster {}
class Ghost implements Monster {}
ArrayList<Monster> monsters = new ArrayList<>();
// legal
monsters.add(new Zombie());
monsters.add(new Ghost());
// legal
monsters.get(i).draw();
You can go with class -> extends solution or this interface -> implements. Either way this is a very bare bones example of a better way to implement your Monsters.

Yes, it is possible, first you need to create an interface, like IMonster which contains a draw method. Then, have each monster type implement this interface.
Your ArrayList will look like this:
List<IMonster> monsters = new ArrayList<IMonster>();
monsters.add(new Ghost());
monsters.add(new Goblin());
So here is an example:
import java.util.ArrayList;
import java.util.List;
public class Monsters {
private static List<IMonster> monsters = new ArrayList<IMonster>();
public static void main(String[] args) {
monsters.add(new Ghost());
monsters.add(new Goblin());
monsters.add(new Devil());
for (IMonster monster : monsters) {
monster.draw();
}
}
}
interface IMonster {
public void draw();
}
abstract class AbstractMonster implements IMonster {
#Override
public void draw() {
System.out.println("Shared drawing code for all monsters");
}
}
class Ghost extends AbstractMonster {
#Override
public void draw() {
super.draw();
System.out.println("Ghost drawing code");
}
}
class Goblin extends AbstractMonster {
#Override
public void draw() {
super.draw();
System.out.println("Goblin drawing code");
}
}
class Devil extends AbstractMonster {
#Override
public void draw() {
super.draw();
System.out.println("Devil drawing code");
}
}

You have to cast your item get from the ArrayList like this -
Object item = Monsters.get(i);
Monster monster = (Monster) item;
monster.draw();
Or better you may use some Interface. You may use an interface (for example Drawable ). Your Monsterand other drawable class would implement it. Then use the ArrayList of Drawable.
interface Drawable{
public void draw();
}
public class Monster implements Drawable {
public void draw(){
//implementation of monster's draw
}
}
...
...
ArrayList<Drawable> monsters = new ArrayList<Drawable>();
...
...
monsters.get(i).draw();

Related

Java OOP instance of class

I have following classes structure extention:
Entity > Creature > (abstract)Player > Mage.
In Mage class I implement interface iCastable with method castSpell(). In main method I create new Mage(...).
Problem is that when I send it as a prop of Player class someMethod(Player player), I cannot use methods implemented from interface iCastable. I can only use methods from Creature class via player.getCreaure.whaterver() because Player extend it. How can I solve that issue?
I do not want to send it as a prop of Mage class, because I want to use all my other classes like Warrior for example. I also want to avoid player instanceof Mage, because if I had 1000 classes I must do 1000 check for every method. Do you have any ideas how to solve that?
EDIT added code
public class Creature extends Entity {...}
public abstract class Player extends Creature {
public Player(String name) {
super(name);
}
public abstract void attack();
}
public class Mage extends Player implements iCastable {
...
#Override
public void castSpecial() {...}
}
public static void main(String[] args) {
Mage mage = new Mage("Mage");
Duel duel = new Duel(mage, monsters);
}
public class Duel {
private Player player;
...
public Duel(Player player, ArrayList<Monster> monsters) {
this.player = player;
...
}
private void castSpecial() {
// error here
player.castSpecial();
}
}
I am trying to do something like player.getInstanceClass(mage, warrior or whatever).cashSpecial()
Your method can be written like this:
private void castSpecial() {
if (player instanceof iCastable) {
((iCastable) player).castSpecial();
}
}
The instanceof performs a runtime check to see if the Player instance has the correct subclass. If the check succeeds then the type cast will also succeed. (If you do the type cast without a "guard", then it will throw an ClassCastException if the player doesn't have the required type.)
Obviously, if the player does not have spell casting ability, the method does nothing.
Note: the interface name iCastable is wrong from two perspectives.
A class or interface name should never start with a lowercase letter.
The name is wrong. ICastable implies that you would "cast" a Mage. In fact, the Mage is the subject, that casts the spell, not the spell that is cast. A better name might be ISpellCaster.

Avoiding the need to cast in java inheritance

Lets say I had a simple inheritance structure like so:
class Shape {
int id;
}
class Circle extends Shape {
int radius;
}
class Square extends Shape {
int length;
}
class ToyBox {
List<Shape> shapes;
}
These objects cannot be augmented in any way (no adding methods/fields/accessors.change the file in any way) and should be treated as immutable/final. I have to return each of these shape objects to another part of the system I am working within with some extra information to go alongside each item. For example:
class extended Shape {
int id;
}
class ExtendedCircle extends ExtendedShape {
public Circle circle;
public Blah circleStuff;
public ExtendedCircle(Circle circle) {...}
}
class ExtendedSquare extends ExtendedShape {
public Square square;
public Blah squareStuff;
public ExtendedSquare(Square square) {...}
}
The only way I can think of accomplishing this task given a ToyBox of shapes is to iterate through the shapes list, do an instance of check and do a cast to circle, square etc. to then construct each of the corresponding "Extended" objects. This makes me a little uncomfortable so i am wondering if there is another way to design such a system?
If you need to avoid casting and using instanceof operator you probably would like to consider using Vistor design pattern. Applying it to your example if might looks as following:
class Shape {
int id;
public void visitingShape(ToyBox box) {
box.visitingShape(this);
}
}
class Circle extends Shape {
int radius;
public void visitingShape(ToyBox box) {
box.visitingCircle(this);
}
}
class Square extends Shape {
int length;
public void visitingShape(ToyBox box) {
box.visitingSquare(this);
}
}
class ToyBox {
List<Shape> shapes;
public visitingShape(Shape shape) {
// Do logic related to the shape
}
public visitingCircle(Circle shape) {
// Do logic related to the circle
}
public visitingSquare(Square shape) {
// Do logic related to the square
}
}
I can propose an approach which is closer to pattern-matching. It doesn't solve the problem using inheritance, but it should give the same advantages as a visitor pattern without the heavyweight aspect of it.
Simply introduce a ShapeType enumeration, make each shape return its type and use a switch-case structure to implement your logic. Might be more readable.
It seems like you're in a pretty tough spot not owning the shape classes but I think you could add shape proxies. It adds an additional layer but provides the ability to extend the shapes as well as additional control over the interface if you'd need it.
Let's say, given a Shape as follows:
public class Shape {
public void doSomethingWithShape() {}
}
You provide a ShapeProxy like so (implementing the Shape interface and providing a proxy into it):
public class ShapeProxy extends Shape implements IShapeProxy {
// Optional
#Override
public void doSomethingWithShape() {
// Do something extra if needed.
}
// From IShapeProxy
#Override
public ExtendedShape getExtended() {
return new ExtendedShape(this);
}
}
Likewise, you would have proxies for each additional shape:
public class CircleProxy extends Circle implements IShapeProxy {
#Override
public ExtendedCircle getExtended() {
return new ExtendedCircle(this);
}
}
And, of course, you could use it like this:
public static void main(String[] args) {
List<IShapeProxy> shapes = new ArrayList<>();
shapes.add(new ShapeProxy());
shapes.add(new CircleProxy());
shapes.add(new SquareProxy());
List<ExtendedShape> extendedShapes = new ArrayList<>();
shapes.forEach(s -> extendedShapes.add(s.getExtended()));
}
I would prefer it this way but if you couldn't change the type of List then you could still shove them in as Shapes and cast to get the extended type. Still, it's a common cast that wouldn't require knowledge about the type of shape at hand.
If that seems like too much or if you'd like to separate the extending from the proxy, you can combine the proxy idea with Dici's suggestion and add a type like so (changes to the interface not shown):
public enum ShapeType {
SHAPE, CIRCLE, SQUARE
}
public class CircleProxy extends Circle implements IShapeProxy {
// From IShapeProxy
#Override
public ShapeType getType() {
return ShapeType.CIRCLE;
}
}
// And...
for (IShapeProxy proxy : shapes) {
switch (proxy.getType()) {
case SHAPE:
// Build the extended type.
break;
...
}
}
}

Run Time Polymorphism

class A {
public void display(){
System.out.println("From Class A");
}
}
class B extends A {
public void display() {
System.out.println("From Class B");
}
}
public class Test {
public static void main(Strings[] args){
A a = new A();
A b = new B()
a.display();
b.display();
}
}
Output:
From Class A
From Class B
Now, I am getting the output as expected.
But I want to know why I am using A b = new B(), when same thing I can achieve by using
B b = new B().
What is the advantage of using former techniques, where and when it is beneficial for me?
Lets take an example here. We all know birds can fly, but there are some exceptions. We know from their behavior, so lets model this.
Generally, birds can fly, so:
class Bird {
void fly() {
System.out.println("I can fly");
}
}
class Eagle extends Bird {
void fly() {
System.out.println("I can fly very high");
}
}
We all know that ducks can't fly, but we don't say it for all birds. We say at runtime whether a specific bird can fly or not, depending on the bird.
class Duck extends Bird {
void fly() {
System.out.println("I can walk or swim only");
}
}
class FlightDemo {
public static void main(String[] args) {
Bird bird = new Bird();
bird.fly(); // output: I can fly
Bird eagle = new Eagle();
eagle.fly(); // output: I can fly very high
Bird duck = new Duck();
duck.fly(); // output: I can walk or swim only
}
}
You saw that at runtime it's decided that ducks can't fly. You can override its fly behavior and it would walk or swim. We saw that Duck IS a Bird, and it can't fly, so we have overridden its behavior, and still Duck IS a Bird, and it can walk or swim.
In your example, it doesn't matter which way you chose. Your example doesn't show the power of polymorphism.
Let's see a trivial example of Polymorphism:
interface Shape{
void draw();
}
class Rectangle implements Shape{
public void draw(){
System.out.println("Drawing Rectangle.");
}
}
class Triangle implements Shape{
public void draw(){
System.out.println("Drawing Triangle.");
}
}
class Circle implements Shape{
public void draw(){
System.out.println("Drawing Circle.");
}
}
Rectangle, Triangle, and Circle are just implementing their own definition of draw function.
Now, suppose you've to implement a drawAllShapes method in your Main class, which takes a bunch of shapes and print them all. But without polymorphism this can be hectic, as there can be different types of shapes. Now, here comes polymorphism to save us.
class RandomShapeFactory{
public static Shape createRandomShape(){
Shape randomShape;
Random random = new Random();
int randomNo = random.nextInt() % 3 + 1;
if (randomNo == 1){
randomShape = new Rectangle();
}
else if (randomNo == 2){
randomShape = new Triangle();
}
else{
randomShape = new Circle();
}
return randomShape;
}
}
class Main{
public static void main(String[] args){
Shape[] shapes = new Shape[10];
for (int i = 0; i < shapes.length; i++){
shapes[i] = RandomShapeFactory.createRandomShape();
}
drawAllShapes(shapes);
}
public static void drawAllShapes(Shape[] shapes){
for (int i = 0; i < shapes.length; i++){
shapes[i].draw();
}
}
}
This implementation of drawAllShapes doesn't have to know whether the Shape at index i is a Circle or Triangle or what, whichever Shape it is, it just calls their implementation of the draw method.
main method has all random shapes, and when passed to the drawAllShapes method, their relative implementations are invoked.
This kind of implementation also follows the Open/Closed Principle, that if you want, in future, to add some more Shapes to the hierarchy, drawAllShapes method doesn't have to know about the new shapes either, just add new classes and implement the Shape interface, and drawAllShapes will work with those shapes too.
See the above example in action here.

Java Get the List of an Object from another Class

I'm having two classes : WorldOfRobots and Robot (abstract). Both are public. World of robots is basically an arraylist of Robot.
Then I have a class telebot which is an extension of Robot.
I'm trying to build a method in the class Telebot which will identify and get the list of robots where the current object Telebot is.
For example:
I create 2 World of Robots (wor1 and wor2) and then 1 telebot (r1).
I add r1 in wor1.
I'd like to get a way to get the list of robots of wor1 in a method of the class telebot.
Here is a bit of code.
abstract class Robot {
// content
}
public class Telebot extends Robot
{
// instance variables - replace the example below with your own
private WorldOfRobots wor;
public Telebot(String newName, String newDirection)
{
super(newName, newDirection);
}
public void something {
// here I'm trying to get the list
wor = new WorldOfRobots();
ArrayList<Robot> robots = wor.getList();
// Unfortunately this solution doesn't work cause I'm creating a new WOR. What I want is to get the WOR where the Telebot belong.
}
}
public class WorldOfRobots {
// List of robots
private ArrayList<Robot> robots;
public WorldOfRobots() {
robots = new ArrayList<Robot>();
}
public ArrayList<Robot> getList() {
return robots;
}
}
Thanks for your help.
You can refactor your class to something like this ...
public class Telebot extends Robot {
//your code and constructer here
public void something(WorldofRobots container){
//this is the list containing your instance of telerobot, use it as you like
}
}
Now from outside classes you can invoke robotInstance.something(listOfRobot);
I am not sure how your classes are exactly interacting so I cannot expand on using this method more.
abstract class Robot {
private WorldOfRobots world;
public void setWorld(WorldOfRobots world)
{
this.world=world;
}
// content
}
public class Telebot extends Robot
{
public Telebot(String newName, String newDirection)
{
super(newName, newDirection);
}
public void doSomething()
{
world.doSomethingElse();
}
}
public class WorldOfRobots {
// List of robots
private ArrayList<Robot> robots;
public WorldOfRobots() {
robots = new ArrayList<Robot>();
}
public void addRobot(Robot robot)
{
robots.add(robot);
robot.setWorld(this);
}
}
Storing a reference for the WorldOfRobots in the Robot class is reasonable in this case. If you want a robot to belong to multiple WorldOfRobots then change the world varible to List.

AbstractFactory design pattern in real life

As you all know that the AbstractFactory helps creating object without knowledge of creation process. But the complexity of the pattern will increase by the time, when new factory is added or large modifications are made within the factory class. This will require a heavy change on abstract factory creator class.
I used to use AbstractFactory, but with my own modification & it's like: Replace abstract factory creator class with empty interface, which will be implemented by factory classes. Then cast returned object from FactoryCreator class to the real factory I want. This worked, but I wonder if this breaks the pattern or is it a bad practice on the pattern or does it have any drawback that would lead to the same complexity in the future development?
Below is a very simple implementation of the pattern that I took from the book & my modifications as well:
Shape factory:
public interface Shape {
void draw();
}
public class Circle implements Shape {
#Override
public void draw() {
// Draw circle
}
}
public class Rectangle implements Shape {
#Override
public void draw() {
// Draw rectangle
}
}
public class ShapeFactory implements IFactory {
public Shape getShape(String shape) {
if (shape.equalsIgnoreCase("CIRLE")) {
return new Circle();
} else if (shape.equalsIgnoreCase("RECTANGLE")) {
return new Rectangle();
}
return null;
}
}
//public class ShapeFactory extends AbstractFactory {
// #Override
// public Color getColor(...) {
// //
// }
// #Override Shape getShape(...) {
// //
// }
//}
Color factory:
public interface Color {
void fill();
}
public class Red implements Color {
#Override
public void fill() {
// Fill red
}
}
public class Green implements Color {
#Override
public void fill() {
// Fill green
}
}
public class ColorFactory implements IFactory {
public Color getColor(String color) {
if (color.equalsIgnoreCase("RED")) {
return new Red();
} else if (color.equalsIgnoreCase("GREEN")) {
return new Green();
}
}
}
//public class ColorFactory extends AbstractFactory {
// #Override
// public Color getColor(...) {
// //
// }
// #Override Shape getShape(...) {
// //
// }
//}
Factory creator interface:
public interface IFactory { }
//public abstract class AbstractFactory {
// abstract Color getColor(String color);
// abstract Shape getShape(String shape) ;
//}
Factory creator:
public class FactoryCreator {
public static IFactory getFactory(String factoryName) {
if (factoryName.equalsIgnoreCase("SHAPE")) {
return new ShapeFactory();
} else if (factoryName.equalsIgnoreCase("COLOR")) {
return new ColorFactory();
}
return null;
}
}
Usage:
public class demo {
ShapeFactory shapeFactory = (ShapeFactory)FactoryCreator.getFactory("SHAPE");
ColorFactory colorFactory = (ColorFactory)FactoryCreator.getFactory("COLOR");
shapeFactory.getShape("CIRCLE").draw();
shapeFactory.getShape("RECTANGLE").draw();
colorFactory.getColor("RED").fill();
colorFactory.getColor("GREEN").fill();
}
So the question in essence boils down to difference between abstract class and interface.
There are many sources on this discusion:
see here
What you need to understand about the patterns is that they are designed to be template for solution. It will happen rarely that you can copy paste pattern with zero modification and expect to fit your problem perfectly.
As for your question, can you implement AbstractFactory pattern with a FactoryCreator interface instead of abstract class ?
Surely you can, this is an implementation detail which does not break the intent of the pattern.
Abstract Factory offers the interface for creating a family of related objects, without explicitly specifying their classes.
Edit
You are looking at one specific implementation of this pattern in which author decided to implement the template with abstract class.
Design patterns are not a guarantee to to the right thing... you have to use your head first...
history showed that many people had a certain problem with [xxx] and a lot of people could solve the problem with Design-Pattern [yyy]. That's how desgin pattern evoveld and how they are defined.
You cannot say i'll implement this (or that) pattern and i'll have no problems anyway. you have to think, describe your problem and see if this pattern would help you to design your architecture.
Obviously: your programm implementation is so simple that abstractFactory is overhead, and you already solved that with using mere interfaces.
ok, let's speak the obvoius:
AbstractFactory is not the solution to your problem:
first: define your problem: i want to create parametrized objects in a simple way. a) parametrized with shape and color and b) simple way
possible solution: factory-methode (think: you have the interface Shape with two implementations and the interface Color with two implementations)
public ShapeFactory{
public static Shape create(String shape){
if ("CICRCLE".equals(shape)) //your code from above
}
}
and a Color factory
public ColorFactory{
public static Color createColor(String color){
if("GREEN".equals(color) ) // your code from above
}
}
using these design pattern you can solve your problem as defined above... (you can make one factory wich provides factory-methods for both interfaces, if you want to make it even shorter)
As per my understanding in the above problem, one wants to create a shape and then fill color in it. If thats the case one can make it bit better by adding Builder pattern on top of factory.
class ShapeBuider
{
private String color;
private String shape;
/**
* #param color the color to set
*/
public void setColor(String color) {
this.color = color;
}
/**
* #param shape the shape to set
*/
public void setShape(String shape) {
this.shape = shape;
}
public void build()
{
// create shape
// create color
// fill shape with color
}
public Object get()
{
// return the created object in build method here.
return null;
}
}
This builder approach will make sure that the right color is applied to right shape.

Categories