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.
Related
I am relatively new to Java and programming, so I apologize if this question seems stupid. I am creating a battle-game for a Java programming class -- I have a Hero class with some basic methods and a subclass Paladin that extends Hero but with its own unique methods added in. I want to have a Battleground object that passes in ANY Hero class but then check which specific subclass was passed in. How do I determine which of the Hero subclasses were passed in?
public class Hero {
private String name;
private int hitPoints;
public Hero (String name, int hitPoints) {
this.name = name;
this.hitPoints = hitPoints;
}
public String getName() { return this.name; }
public int getHitPoints() { return this.hitPoints; }
public void takeDamage(int amount) { this.hitPoints -= amount; }
}
And here is the Paladin Class
public class Paladin extends Hero {
public Hero (String name, int hitPoints) {
super(name, hitPoints);
}
public void heal(int amount) {
this.hitPoints += amount;
}
}
So in the battleground class, I have a method that attempts (incorrectly) to check if the hero passed in is a Paladin. How would I go about doing this? The if statement is a placeholder psuedo-code just to clarify what I mean.
public class Battleground {
private Hero player;
public Battleground (Hero player) {
this.player = player;
}
public void startRound() {
// HERE!!
if (player.equals(Paladin)) {
player.heal();
}
}
}
Thinking in terms of what your classes are actually modelling, it doesn't make much sense for a battleground to know that a Paladin heals themselves at the start of a round, nor for the battleground to be responsible for making sure the Paladin heals themselves.
A more sensible design would be for the game to inform the hero that the round has started, and let the particular Hero subclass control what that kind of hero does when the round starts. For example:
public class Hero {
// ...
public void onRoundStart() {
// do nothing
}
}
public class Paladin extends Hero {
// ...
#Override
public void onRoundStart() {
// your heal method takes an int as its argument
heal(10);
}
}
public class Battleground {
// ...
public void startRound() {
// let the particular Hero subclass control what happens
player.onRoundStart();
// ...
}
}
This way you don't need any if statements or instanceof checks, but also the code defining a Paladin's behaviour is in the Paladin class where it sensibly belongs. If you want to change the rules for Paladins later, it will be easier to know which class you need to edit.
This kind of refactoring is called "replace conditional with polymorphism".
Using Instanceof is Considered a Code Smell Sometimes
Using instanceof can be considered to be a code smell - which means a bad practice.
There is an alternative for you to consider.
Add the heal() method to the Hero class, but leave the implementation blank.
Put only an implementation in the Paladin class. Then, even though heal() will be called on all players, it will only do something inside Paladins.
However... if you still need to detect the class type...
Ways to Detect the class
There are multiple ways to differentiate between classes.
Instance of is one.
Another is having different constructors.
A third is having an ENUM or String field called EntityType.
In your case, I think instanceof or using a special field make the most sense.
Instanceof
if(player instanceof Paladin)
Using a Special Field
Quick Example Hero
public class Hero {
private String name;
private int hitPoints;
private int HeroType;
public Hero (String name, int hitPoints) {
this.name = name;
this.hitPoints = hitPoints;
this.heroType = BASIC_HERO;
}
public static int BASIC_HERO = 0;
public static int PALADIN_HERO = 1;
...
}
Quick Example Paladin
public class Paladin extends Hero {
public Paladin(String name, int hitPoints) {
super(name, hitPoints);
this.heroType = PALADIN_HERO;
}
}
Detecting the Type
You would have a method in both classes called getHeroType().
if(hero.getHeroType == Hero.PALADIN_HERO){
}else if(hero.getHeroType == Hero.BASIC_HERO){
}
If you want, you can use to check the class of the object:
if (player instanceof Paladin)
No question, this will work. If you don't have a lot of "special" behaviour and a limited small amount of cases, that can be a reasonable solution. But assuming that your game will end up with a lot of special handling for each subclass of Hero and probably not only in the startRound() method of your Battlefield class, your code will someday be cluttered with these instanceof checks. Same applies, if you use a specific type field within the Hero class.
In that case a better solution might be to relocate the logic into special classes and try to avoid type checks if possible or at least have a well defined place for them, if necessary.
Update: removed faulty demo implementation
You can always do player.getClass to get actuall class. As for if statements you can use instanceof operator.
So
if (player instanceof Paladin) {
((Paladin)player).heal();
}
I would like to create a copy of an object that contains a super class of another object. In this example I want to make a copy of the Box that contains a Toy. But all kind of toys can be in the box. What would be the best way to create the copy constructor in Toy?
class Box {
Toy toy;
public Box(Toy toy) {
this.toy = toy;
}
public Box(Box box) {
this.toy = new Toy(box.getToy());
}
}
abstract class Toy {
public Toy(String name) {
// ...
}
}
class Car extends Toy {
public Car(String name) {
super(name);
// ...
}
}
class Puppet extends Toy {
public Puppet(String name) {
super(name);
// ...
}
}
I don't really have an idea how to approach this problem.
Make Toy have an abstract method copy() with return type Toy. Then you will be forced to override this in Car and Puppet. In the copy constructor for Box you can use box.getToy().copy().
You can override the clone method of each Toy's subclass and then :
public Box(Box box) {
this.toy = (Toy) box.getToy().clone();
}
Alternatively, if you have a constant number of types of toy, you can use an enumeration instead of a class.
i think this structure can help you to have an idea,in this case we pass an Object toy using Box Constructor to SuperClass(Toy) and in Toy Class we have a Constructor to Accept an Object from Toy Class then it's call getInstance Method for Initialize toy object(just for example).
class Box extends Toy
{
public Box(Toy toy)
{
super(toy);
}
}
Class Toy
{
private static Toy toys = new Toy();
Toy(){}
Toy(Toy toy)
{
toy = Toy.getInstance();
}
public static Toy getInstance()
{
return toys;
}
}
and either,if you don't want other Classes(sub class) to don't see a specified methods and attributes just make them private,and if you want sub classes haven't access to set and get methods too,make them private only!
What I try to accomplish is to invoke the Interface of a specific class.
I use a Enum to fill in the .class and to get the Interface of that Class.
So how can I return the interface?
I would like to avoid reflection if possible.
Thanks in advance.
public interface GameInterface {
void start();
void sop();
}
public enum Game{
MINESWEEPER(MineSweeper.class),
MARIO(Mario.class);
private Class c;
public Game(Class c) {
this.c = c;
}
public GameInterface getGameInterface() {
// return Interface of the class
// So I can call for instance MINESWEEPER.getGameInterface().start()
// At this momement I use return:
// ((GamemodeInterface)this.c.getDeclaredMethod("getInstance", new Class[0]).invoke(null, new Object[0]));
// *MineSweeper and Mario are Singleton, thats why getInstance
}
}
Clarification:
The main goal is to acces Start() and Stop() methods at MineSweeper and Mario class.
The usage should be something like: MINESWEEPER.getGameInterface().start()
But at this moment I don't know a solid solution to get the Interface with knowing of the .class.
A better idea:
Implement GameInterface to each Game of your class with implying name of your choice.
Declare enum with abstract function createGame and return with the instance of the Game class you are expecting with implementation of this createGame function to each enum constant:
class MineSweeper implements GameInterface
{
// your code
}
class Mario implements GameInterface
{
// your code
}
public enum GameType
{
MINESWEEPER
{
public GameInterface createGame()
{
return new MineSweeper();
}
},
MARIO
{
public GameInterface createGame()
{
return new Mario();
}
}
public abstract GameInterface createGame();
}
If you intended to use singleton pattern, although i could not be so sure from your question but as #GaborSch has suggested: you could make use of MineSweeper.getInstance() function inside the createGame() of enum constants. However, try thinking to use an enum while implementing a Singleton too, as is suggested in Effective Java book with detail explanation.
I would like my BallUserInterfaceFactory to return an instance of a user interface that has the proper generic type. I am stuck in the example below getting the error:
Bound mismatch: The generic method getBaseballUserInterface(BASEBALL)
of type BallUserInterfaceFactory is not applicable for the arguments
(BALL). The inferred type BALL is not a valid substitute for the
bounded parameter
public class BallUserInterfaceFactory {
public static <BALL extends Ball> BallUserInterface<BALL> getUserInterface(BALL ball) {
if(ball instanceof Baseball){
return getBaseballUserInterface(ball);
}
//Other ball types go here
//Unable to create a UI for ball
return null;
}
private static <BASEBALL extends Baseball> BaseballUserInterface<BASEBALL> getBaseballUserInterface(BASEBALL ball){
return new BaseballUserInterface<BASEBALL>(ball);
}
}
I understand that it cannot guarantee that BALL is a Baseball, and so there is a parameter type mismatch on the getBaseballUserInterface method call.
If I cast the ball parameter in the getBaseballUserInterface method call, then I get the error:
Type mismatch: cannot convert from BaseballUserInterface<Baseball>
to BallUserInterface<BALL>
Because it can't guarantee that what I am returning is the same type of BALL.
My question is, what is the strategy for dealing with this situation?
(For completeness, here are the other classes required in the example)
public class Ball {
}
public class Baseball extends Ball {
}
public class BallUserInterface <BALL extends Ball> {
private BALL ball;
public BallUserInterface(BALL ball){
this.ball = ball;
}
}
public class BaseballUserInterface<BASEBALL extends Baseball> extends BallUserInterface<BASEBALL>{
public BaseballUserInterface(BASEBALL ball) {
super(ball);
}
}
This is a wrong design pattern. Rather than using one generic method and an if ladder, you should instead use overloading. Overloading eliminates the need for the if ladder and the compiler can make sure the correct method is invoked rather than having to wait till runtime.
eg.
public class BallUserInterfaceFactory {
public static BallUserInterface<Baseball> getUserInterface(
Baseball ball) {
return new BallUserInterface<Baseball>(ball);
}
public static BallUserInterface<Football> getUserInterface(
Football ball) {
return new BallUserInterface<Football>(ball);
}
}
This way you also get the added benefit of compile time errors if your code cannot create a BallUserInterface for the appropriate ball.
To avoid the if ladder you can use a technique known as double dispatch. In essence, we use the fact that the instance knows what class it belongs to and calls the appropriate factory method for us. For this to work Ball needs to have a method that returns the appropriate BallInterface.
You can either make the method abstract or provide a default implementation that throws an exception or returns null. Ball and Baseball should now look something like:
public abstract class Ball<T extends Ball<T>> {
abstract BallUserInterface<T> getBallUserInterface();
}
.
public class Baseball extends Ball<Baseball> {
#Override
BallUserInterface<Baseball> getBallUserInterface() {
return BallUserInterfaceFactory.getUserInterface(this);
}
}
To make things a little neater, it's better to make getBallUserInterface package private and provide a generic getter in BallUserInterfaceFactory. The factory can then manage additional checks like for null and any thrown exceptions. eg.
public class BallUserInterfaceFactory {
public static BallUserInterface<Baseball> getUserInterface(
Baseball ball) {
return new BallUserInterface<Baseball>(ball);
}
public static <T extends Ball<T>> BallUserInterface<T> getUserInterface(
T ball) {
return ball.getBallUserInterface();
}
}
The Visitor Pattern
As pointed out in the comments, one problem of the above is it requires the Ball classes to have knowledge of the UI, which is highly undesirable. You can, however, use the visitor pattern, which enables you to use double dispatch, but also decouples the various Ball classes and the UI.
First, the necessary visitor classes, and factory functions:
public interface Visitor<T> {
public T visit(Baseball ball);
public T visit(Football ball);
}
public class BallUserInterfaceVisitor implements Visitor<BallUserInterface<? extends Ball>> {
#Override
public BallUserInterface<Baseball> visit(Baseball ball) {
// Since we now know the ball type, we can call the appropriate factory function
return BallUserInterfaceFactory.getUserInterface(ball);
}
#Override
public BallUserInterface<Football> visit(Football ball) {
return BallUserInterfaceFactory.getUserInterface(ball);
}
}
public class BallUserInterfaceFactory {
public static BallUserInterface<? extends Ball> getUserInterface(Ball ball) {
return ball.accept(new BallUserInterfaceVisitor());
}
// other factory functions for when concrete ball type is known
}
You'll note that the visitor and the factory function have to use wildcards. This is necessary for type safety. Since you don't know what type of ball has been passed, the method cannot be sure of what UI is being returned (other than it is a ball UI).
Secondly, you need to define an abstract accept method on Ball that accepts a Visitor. Each concrete implementation of Ball must also implement this method for the visitor pattern to work correctly. The implementation looks exactly the same, but the type system ensures dispatch of the appropriate methods.
public interface Ball {
public <T> T accept(Visitor<T> visitor);
}
public class Baseball implements Ball {
#Override
public <T> T accept(Visitor<T> visitor) {
return visitor.visit(this);
}
}
Finally, a bit of code that can put all this together:
Ball baseball = new Baseball();
Ball football = new Football();
List<BallUserInterface<? extends Ball>> uiList = new ArrayList<>();
uiList.add(BallUserInterfaceFactory.getUserInterface(baseball));
uiList.add(BallUserInterfaceFactory.getUserInterface(football));
for (BallUserInterface<? extends Ball> ui : uiList) {
System.out.println(ui);
}
// Outputs:
// ui.BaseballUserInterface#37e247e2
// ui.FootballUserInterface#1f2f0ce9
This is a VERY GOOD question.
You could cast brutely
return (BallUserInterface<BALL>)getBaseballUserInterface((Baseball)ball);
The answer is theoretically flawed, since we force BASEBALL=Baseball.
It works due to erasure. Actually it depends on erasure.
I hope there is a better answer that is reification safe.
public class BaseballUserInterface extends BallUserInterface<Baseball> {
public BaseballUserInterface(Baseball ball) {
super(ball);
}
}
You are using the BallUserInterface as a result of the factory method. So, it can be hidden which concrete ball is used:
public class BallUserInterfaceFactory {
public static BallUserInterface<?> getUserInterface(Ball ball) {
if(ball instanceof Baseball){
return getBaseballUserInterface((Baseball)ball);
}
return null;
}
private static BaseballUserInterface getBaseballUserInterface(Baseball ball){
return new BaseballUserInterface(ball);
}
}
If the client is interested in the type of the ball you should offer a factory method with the concrete ball as parameter:
public static BaseballUserInterface getUserInterface(Baseball ball){
return new BaseballUserInterface(ball);
}
I am unsure as to what the best OO design approach should be regarding a particular State pattern I am implementing. Please consider the following:
public class World {
private Animal dog_;
private Animals cats_;
…..
public void sendDogRequest(DogRequest request) {
dog_.sendRequest(request);
}
…
public Cat getCat(String catName) {
…
return cat;
}
...
}
public class Animal<RequestType extends Request, StateType extends State> {
private State<StateType> currentState_;
….
public void sendRequest(RequestType request) {
request.sendToState(currentState_);
}
public void setState(StateType state) {
currentState_ = state;
}
}
public class Dog extends Animal<DogState> {
…
}
public class DogState extends State {
public DogState(Dog dog) {
…
}
public void seeCat(Cat cat) { }
}
public class OnLeashState extends DogState {
public void seeCat(Cat cat) {
dog.setState(new BarkingState());
}
}
public class OffLeashState extends DogState {
public void seeCat(Cat cat) {
dog.setState(new ChasingAfterAnimalState(cat));
cat.sendRequest(new RunAwayRequest(cat));
}
}
public interface Request<StateType extends State> {
public void sendToState(StateType state);
}
public class DogRequest extends Request<DogState> { }
public class SeeCatRequest extends DogRequest {
private Cat cat_;
public SeeCatRequest(Cat cat) {
cat_ = cat;
}
public void sendToState(DogState state) {
state.seeCat(state);
}
}
public class Controller() {
public Controller(World model, View view) {
…
}
...
public void catSelected(String catName) {
Cat cat = world.getCat(catName);
Dog dog = world.getDog();
world.sendDogRequest(new SeeCatRequest(cat));
}
…
}
My area of hesitation is with the usages of the word new here, ie. instantiating a new SomeState() with another State, or new SomeRequest() within the Controller or another State. It seems to me that this would produce high coupling between the States and their siblings, as well as the Controller and States.
The requirements are as follows:
It MUST be possible to add new States, for example adding a SniffingState.
It also MUST be possible to replace existing States with new ones. For example, I should be able to replace OffLeachState with a different OffLeashState that performs a different action. For example (for some reason the code won't format):
public class OffLeachState2 extends DogState {
public void seeCat(Cat cat) {
if (dog.knows(cat)) {
// dog changes to "PlayWithCatState"
// cat gets a "PlayWithDog" request
} else {
// dog changes to "ChaseAnimalState"
}
}
}
Finally, all changes within the World class MUST be logged. That means that the World class has a logger which is keeping track of everything that is going on. This is also because the World class is a model, and has to fire off a notifyObservers() so that the view knows to do something.
My question is, where should the states, requests etc be stored? For example:
Should there be state "getters" in Dog? for example, dog.getBarkingState(), dog.getOnLeashState(), etc? This seems to make sense, but it doesn't make the Dog class resistant to change. Ie, every time I add a new DogState class, I also have to make sure that Dog has a getter for it. Also, the World doesn't know about these changes, so it doesn't log them nor notify observers.
Should there be a class called DogStates and I can run DogStates.getBarkingState()? Again, similar problems to the one above.
Should they be a part of the World class? For example, world.setDogState(dog, world.getDogBarkingState()? This would solve the logging/updating problem, but puts too much responsibility on the World class.
Should it be some combination thereof, for example world.setState(dog, dog.getBarkingState()? This COULD be good, but doesn't assure type safety. For example, I could pass in a Dog object with a CatState, and it wouldn't know the difference.
Solution #4 seems the best to me, but I would like some other opinions about this issue.
The same question applies to the Request object. I originally wanted to send Requests by Strings which were associated with an object, for example world.sendRequest(dog, DogRequests.SEE_CAT), but then I couldn't pass the cat object as an argument.
Thank you very much for your time!
1.) This looks like a programming exam question. In such scenarios, if unsure what to do, use a Pattern! So every State should be generated by a StateFactory and give the Factory instance some information about the World so it can decide which specific State instance to create.
Here's the logging stuff:
public class World implements StateChangeListener {
private Animal dog_;
private Animals cats_;
private final List<StateChangeListener> listeners = new ArrayList<StateChangeListener>();
public World() {
listeners.add(this);
}
// Instead of sending DogRequests to Dogs via the sendDogRequest method:
public <RequestType extends Request> void sendRequest(
Animal<RequestType, ?> animal, Request<RequestType> request) {
animal.sendRequest(request);
for(StateChangeListener listener : listeners) {
listener.stateChanged(animal, request);
}
}
public void stateChanged(Animal<?, ?> animal, State<?> state) {
// ... log here ...
}
...
And that Factory stuff (probably a bit scatterbrained, Generics might not work correctly ;o).
public enum LocationEnum {
HOME, PARK, POND, FOREST
}
public interface StateFactory<StateType extends State> {
State<StateType> create(Animal<StateType, ?> animal, Context context);
}
// Do stuff Dogs do.
public class DogStateFactory<DogState> {
public State<DogState> create(Animal<DogState, ?>, Context context) {
if(context.currentAnimalLocation==LocationEnum.POND) {
return new IgnoreEverythingState();
}else if(context.currentAnimalLocation==LocationEnum.HOME){
return new PerpetualBarkState();
}else {
return new FollowEveryCatState();
}
}
}
public class Animal<RequestType extends Request, StateType extends State> {
private StateFactory<StateType> stateFactory;
private State<StateType> currentState_;
public void sendRequest(Request<RequestType> request) {
request.sendToState(currentState_);
}
// A specific animal knows what it wants to do, depending on it's current
// state and it's situational context. We don't want other animals
// to set the state for us.
public void determineState() {
currentState_ = stateFactory.create(this, new Context(...));
// One might want to extend the messaging stuff in a way that
// the World instance can log this state change.
}
}
public class Dog extends Animal<DogRequest, DogState> {
public Dog() {
this.stateFactory = new DogStateFactory<DogState>();
}
}
2.) If you want the World to know everything happening in it, you could substitute the state setters whith messages and let the World instance listen to everybody's state changes.