If Downcasting Should Be Avoided, What Should I Do? - java

have the following interface class:
public interface IGameObject {
String gameObjectID();
String gameObjectName();
void isActionValid(String action);
void viewActions();
}
I have the following abstract class that implements the above interface.
package gameprobjectpackage;
public abstract class Weapon implements IGameObject {
//Left out getters/setters to keep it simple
private String gameOjectID;
private String gameObjectName;
private int damage;
public Weapon(String gameOjectID, String gameObjectName,int damage) {
super();
this.gameOjectID = gameOjectID;
this.gameObjectName = gameObjectName;
this.damage = damage;
}
I've come across a few posts that suggest downcasting should be avoided. I understand why, BUT, my question is what do I do if I need to access a method that is specific to a sub class. For example:
public class ChargeGun extends Weapon {
private String [] chargeGunActions;
public ChargeGun(String gameOjectID, String gameObjectName, int damage) {
super(gameOjectID, gameObjectName, damage);
chargeGunActions = new String [3];
chargeGunActions[0] = "Charge and Fire";
chargeGunActions[1] = "Release";
chargeGunActions[2] = "Drop Gun";
}
//This method is only meant for gun, and this type of gun is the only one in my game.
//This method, I don't belive should be in the abstract method weapon, because NOT every weapon is a gun.
public void reloadGun()
{
}
I store in in an interventory hashmap like so:
Map<String,IGameObject> inventory = new HashMap<String,IGameObject>();
When I retrieve it, I will get an IGameObject, how do I properly cast it, so that I can access the method in ChargeGun?

You can use the visitor pattern which frees you from casting. The idea is simple : You have an inventory of IGameObject which would have a method accept(GameObjectVisitor v) which directly calls v.visit(this). In your GameObjectVisitor, you just have to implement visit methods for each implementations : For example visit(Chargegun g), visit(Sword s), etc...
To explain it another way, it's like the principle of a boomerang : The GameObjectVisitor calls item.accept(this), and the Item implement accept(GameObjectVisitor g) with a simple g.visit(this).
By doing this, the Visitor has multiple visit methods for each implementation and can do specific stuffs without having to cast/using instanceof.

Related

OOP - Interface inheriting an abstract class alternative

Let's say that I have an interface IMazeRoom
This interface has a function getAdjacentRooms()
Furthermore, Mazerooms have to be instanciated as IMazeRoom room1 etc.
(All of the above cannot be changed)
Let's say these classes are implementing the interface:
TrapRoom, FreeRoom, MobRoom, TreasureRoom
I want to the following functions/variables to be used in all of those subclasses
Players[] playersInRoom, setSize(), isAdditionValid(Player p)
I want to use inheritence with the three functions/variable above without modifying the interface, or duplicating the code throughout the four subclasses.
What I have tried so far
Making an abstract interface MazeRoom which implements IMazeroom, and is implemented by the four subclasses. This does not work as a constraint of this project is that the rooms have to be instantiated as IMazeroom room and doing this would lead to instantiation Mazeroom room If I wanted to use the new functions meantioned above. Also IMazeRooms cannot be modified.
Ideas
I could probably just use another interface with the functions I want to include, which would be implemented by IMazeroom, but this seems weird as this constraint should be here to teach me something, and I do not see the value in just using another interface. Furthermore, using another interface would not really cut down on code duplication, I am looking for something more like a abstract class
(The above is a completely different example from my homework task, as I want to attemp the task on my own)
Edit: Since we cannot change the interface, you can use a DefaultRoom class that implements IMazeRoom.
public class DefaultRoom implements IMazeRoom {
protected Players[] playersInRoom;
/* your standard method implementations */
public boolean isAddtionValid(Player p) {
...
}
}
public interface IMazeRoom {
...
}
Since you have to instantiate it via IMazeRoom myIMazeRoomObject = new DefaultRoom(), as long as you know which kind of Room you are handling, you can simply cast it back:
try {
DefaultRoom myRoom = (DefaultRoom) myIMazeRoomObject;
} catch(ClassCastException ex) {
// we didn't get a DefaultRoom object and now we have to handle that
}
Sidenote: The important thing to note is, that the interface only implements the necessary method getAdjacentRoom, as such it only constitutes information to some (arbitrary) layout that relies on getAdjacentRooms().
Your secondary constraints (immutable interface + instantiation) make it necessary to circumvent something that shouldn't happen with proper OO architecture.
You can seperate the common concrete implemetation into a abstact class and keep the interface.
Rough example based on "I am not allowed to change the interface though":
IMazeRoom:
public interface IMazeRoom {
Set<IMazeRoom> getAdjacentRooms();
}
Common concrete implemetation:
public abstract class CommonRoom {
private final int size;
private final Set<Player> playersInRoom;
private final Set<IMazeRoom> adjacentRooms;
protected CommonRoom(int size, Set<Player> playersInRoom, Set<IMazeRoom> adjacentRooms) {
this.size = size;
this.playersInRoom = playersInRoom;
this.adjacentRooms = adjacentRooms;
}
public int getSize() {
return size;
}
public Set<Player> getPlayersInRoom() {
return playersInRoom;
}
public Set<IMazeRoom> getAdjacentRooms() {
return adjacentRooms;
}
public boolean isAdditionValid(Player player) {
// Some kind of implementation returning true or false...
return !playersInRoom.contains(player);
}
}
TrapRoom:
public class TrapRoom extends CommonRoom implements IMazeRoom {
public TrapRoom(int size, Set<Player> playersInRoom, Set<IMazeRoom> adjacentRooms) {
super(size, playersInRoom, adjacentRooms);
}
}
TreasureRoom:
public class TreasureRoom extends CommonRoom implements IMazeRoom {
public TreasureRoom(int size, Set<Player> playersInRoom, Set<IMazeRoom> adjacentRooms) {
super(size, playersInRoom, adjacentRooms);
}
}
... same implementation as TreasureRoom for additional rooms.
Comment: Now all rooms are treated as IMazeRoom...

Java Factory pattern - How to prevent anonymous subclasses

I'm doing a school assignment where I have to implement the Factory pattern. I have come a long way, but there is one last thing I have not been able to get working.
I have the following classes:
//Human.java
package human;
public abstract class Human{
public static Human create(String namn, String pnr){
char nastsist_char = pnr.charAt(9); // takes second last char in pnr
String nastsist_string = Character.toString(nastsist_char);
float siffra = Float.parseFloat(nastsist_string); //Converts to float
if ((siffra % 2) == 0){ //Checks if even
return new Woman(namn, pnr);
}
else{
return new Man(namn, pnr);
}
}
}
//Man.java
package human;
class Man extends Human{
private final String pnr;
private final String namn;
protected Man(String n, String p){
namn = n;
pnr = p;
}
public String toString(){
return "My name is "+namn+" and I am a man.";
}
}
//Woman.java
package human;
class Woman extends Human{
private final String pnr;
private final String namn;
protected Woman(String n, String p){
namn = n;
pnr = p;
}
public String toString(){
return "My name is "+namn+" and I am a woman.";
}
}
I also have a class called Test.java. Here comes my problem: In Test.java, I want to make it impossible to do the following:
Human h = new Human(){};
i.e., to create an anonymous subclass of Human. Unfortunately, this line of code runs just fine, and an anonymous subclass is created. How can I make this line of code unexecutable/uncompilable?
PS. I have already tried making Human final. It was not allowed to combine final with abstract in a class.
EDIT:
So I got the tip to make the Human constructor protected. Here's what it looks like after the change:
//Human.java
package human;
public abstract class Human{
protected Human(){}
public static Human create(String name, String idNumber){
char secondlast_char = idNumber.charAt(9); // takes second last char in pnr
String secondlast_string = Character.toString(secondlast_char);
float siffra = Float.parseFloat(secondlast_string); //Converts to float
if ((siffra % 2) == 0){ //Checks if even
return new Woman(name, idNumber);
}
else{
return new Man(name, idNumber);
}
}
}
Unfortunately, I still do not get an error neither when running or compiling the code of Test.java, which by the way looks like this:
import human.*;
public class Test{
public static void main(String[] args){
Human h = new Human(){};
}
}
Add a constructor with the default visibility:
public abstract class Human {
Human(){}
}
By default this only allows access to classes within the same package so it is known as "package private".
Use the default modifier for constructors:
Human(){}
Please note that making it impossible to create anonymous classes from your base class is not the main problem with your implementation of the Factory Pattern. The pattern's intention is to encapsulate object creation logic, so that it can be changed easily without affecting the classes that are being instantiated nor the clients that use those instances.
Putting a static factory method into a base class that creates concrete instances of its sub classes defeats the objective of class separation thanks to inheritance as well as the purpose of the factory pattern.
I would seriously consider sticking your factory method into a separate class, e.g. HumanFactoryImpl and provide a corresponding interface.

Access methods on different types

I have something like this:
Figures fig = new Line();
on which Line extends Figure. Figure is an abstract class that only has a method getType() that tells me which figure it is by returning a String;
I have 3 types, Rectangle, Circle and Figure. All of them extend Figures.
Now the real question. I store every single one inside of a List<Figures> and I want to get access to some methods on each object like getStartX(); and getStartY(); and I can't, I only can access the methods that are on Figures also.
Your abstract class should define the getStartX and getStartY method. Either abstract if you want Rectangle, Circle and Figure to have a different behaviour and force them to Override those methods. Else just put the method in Figures it'll be available for use (with the appropriate keyword : public/protected depending your needs).
If you want to use methods that are specific to a class you'll need to check of which instance it is. Something like
for (Figures figure: myList) {
int x = figure.getStartX(); // Method common and declared in Figures
if (figure instanceof Circle) {
System.out.println("Oh no a Circle!");
int radius = ((Circle)figure).getRadius();
...
}
}
For your Rectangle/Line you can define an interface with your 2 methods:
public interface HasEndpoints {
int getEndX();
int getEndY();
}
public class Rectangle implements HasEndpoints {
...
public int getEndX() {return endx;}
...
}
for (Figures figure: myList) {
int x = figure.getStartX(); // Method common and declared in Figures
if (figure instanceof HasEndpoints) { // Rectangle and Line will go there
System.out.println("HasEndpoints implementor");
int endX = ((HasEndpoints)figure).getEndX();
...
}
}
You can use instanceof with if...else and cast dynamically your object
Figure fig = new //Circle()/Triangle()/Rectangle();
if( fig instanceof Circle) {
((Circle) fig).getRadius(); //This method is only available in Circle class
}
You can always cast the Figure to Line, but not the best choice. Depending on the problem, you can apply Visitor Pattern or add those methods to Figure, even when the Circle doesn't have a starting and ending point.
For example
public abstract class Figure{
public abstract void visit(FigureVisitor visitor);
}
public class Line extends Figure{
public void visit(FigureVisitor visitor){
visitor.visitLine(this);
}
}
public interface FigureVisitor{
public void visitLine(Line figure);
public void visitCircle(Circle figure);
}
public class StartingPointsVisitor implements FigureVisitor{
private Double startX;
private Double startY;
private Double endX;
private Double endY;
public void visitLine(Line figure){
this.startX = figure.getStartX(); //No cast needed
...
}
public void visitCircle(Circle figure){
//Stub-method
}
//Getters to read the results
}
Is a more complex solution, but as i said, it depends on the problem, and most of the complex remains in the Visitor
Either getStartX() and getStartY() should be declared in Figure class or you need to cast the object to Line class:
Figure figure = figures.get(0);
if ("line".equals(figure.getType())) {
Line line = (Line)figure;
}
Another option is to use reflection. But you still need to be sure, that the requested method can be called.

How to get Child class?

I want to create an object of child class
more than 100 class extend MasterClass
MasterClass is
public class MasterClass{
int key;
String value;
String displayValue;
boolean status;
}
public class User extends MasterClass{
public User(){ }
}
public class Customer extends MasterClass{
String productName;
public Customer (){ }
}
etc...
i will get a MasterClass object from client, i wanted to type cast that object to respective one
if(masterClass instanceof User) {
User a_user = (User) a_ masterClass;
…
} else if(masterClass instanceof Customer) {
Customer a_customer = (Customer) a_ masterClass;
…
}
if i do this i will end up with 100s of else if.
Please let me know how i can achieve this without else if?
Thanks in advance.
Use polymorphism and generics, as Java intended.
Polymorphism lets you call a method on your object that behaves differently for every type. The easiest way to achieve this is to provide an abstract method in the base class MasterClass and then override it with different functionality in every extended class. You are probably looking for something like this:
class MasterClass {
int age;
// ...
public abstract void doWork();
public int getAge() { return age; }
// .. more methods
}
class User extends MasterClass {
// customize User here
#Override
public void doWork() { /* User does work in some way */ }
}
class Customer extends MasterClass {
// customize Customer here
#Override
public void doWork() { /* Customer does work in some other way */ }
}
// ...
If you are not too familiar with OOP, here is a good introductory tutorial.
If you are not allowed to alter your classes, you can populate a look-up table like HashMap<Class, MyFunctor> where you can assign a different functor for every type of person you have.
Also, you might want to use generics. Generics allow you to capture and restrict the type of objects passed to your methods.
Maybe you can use generics with the constraint T extends MasterClass?
Using basic concepts of Design Pattern you can create a constructor like this in the object where you try to initialize
MasterClass masterClass;
public MyCreatorOject(MasterClass masterClass)
{
this.masterClass = masterClass;
}
later when you create the object it can be
new MyCreatorObject(new User());
or
new MyCreatorObject(new Customer());

How to effectively use static methods?

I am never quite sure that I am using static methods correctly. I understand how they work.
Let's say I have this class called Player(Java):
private int money;
private int lot;
private String piece;
private int playerNum;
public Player(String _piece, int _playerNum)
{
piece = _piece;
lot = 0;
playerNum = _playerNum;
money = 20000;
}
public int getMoney()
{
return money;
}
public int getLot()
{
return lot;
}
public String getPiece()
{
return piece;
}
There are some other methods + setters, but they are specific to the player object I create, now let's say I have a static method like this:
private static int numOfPlayers;
public static int numPlayers()
{
return numOfPlayers;
}
Where should this numOfPlayers method be placed?
Should it be put in my Player class? And should I increment the numOfPlayers varible everytime a new isntance of the player object is created?(via the constructor)
Or, should I have I have the method in my Game class as non-static and just call the method everytime I create a new Player.
Static fields and methods are supposed to represent stateless attributes of a class; i.e. not pertinent to a particular object.
But be careful with multithreading with statics since the whole class has to be locked rather than just one object. This can lead to concurrency bottlenecks.
As for your numOfPlayers, you'll probably end up having a collection of players developed somewhere else, in which case that function will be a method on that collection not in the player class.
Ideally, in my opinion at least, an individual player should not really be concerned about the players collection. Therefore a static function such as the one you propose would not be good design.
It is a matter of design, which obviously includes a lot of personal preference.
You really should have a look at the factory design pattern, which is a good way of handling such cases. Here, you could have a
public class PlayerFactory {
private int numPlayers = 0;
public int getNumPlayers() { ... }
public Player makeNewPlayer(...) { ... }
}
that takes care of A) incrementing the player count appropriately.
Depending on your exact use case and code style, you may prefer one variation or another. But it is good to know these patterns and recognize them. And document them. By calling a class SomethingFactory you do hint for other developers that this class follows the factory pattern, for example.
Note that I did not need to use static in above example, assuming that the factory may only be instantiated once. It is common to see the constructor private and instead the class then has a public static final instance only.
You could also call this class Game or Players...
how about you have a List of Players in your game and the number of players is the size of the List.
When you think you should use static for some functionality, don't do it!
Just play along the old rule to never use anything static until you are old and wise and where you perhaps can use it for some very special corner case.
You can create it like this:
Have class Player like you have
Create class Players
class Players
{
private List<Player> players = new List<Players>;
public void AddPlayer(Player pl)
{
this.players.add(pl);
}
public int GetPlayersCount()
{
return this.players.size();
}
}
If you want, you can make this class "static" using Singleton. But try to avoid static classes.
class Players
{
private List<Player> players = new List<Players>;
private static Players instance;
private Players () {};
public static Players getInstance()
{
if (instance == null)
{
instance = new Players ();
}
return instance;
}
public void AddPlayer(Player pl)
{
this.players.add(pl);
}
public int GetPlayersCount()
{
return this.players.size();
}
}
And use it like this
Players players = Players.getInstance();
players.AddPlayer(....)
I would have the list of Players in another class, e.g. Game as you suggested.
Something like
class Game {
private final List<Player> players = new ArrayList<Player>();
public int getNumOfPlayers() {
return players.size();
}
public void addPlayer(final Player player) {
players.add(player);
}
...
You add a player via your instance of Game, game via game.addPlayer(newPlayer), and get the number of players via game.getNumOfPlayers().
The List of players is dynamically allocated.
As for static or not static, I prefer here the non static version, as the players are part of a Game, and one could consider they may be several games - and players would be part of an instance of Game.

Categories

Resources