Overloading with Polymorphism - java

I'm designing a physics simulator with 3 types of things that can collide.
The most basic [abstract] class is called Item which contains information on mass, position & speed.
There are 3 other types: Circle, Boundary & Photon which extend the Item class and have their own properties.
I have a List<Item> called system which contains various Circles, Boundaries etc and I go through this list to check for collisions by using a method: system.get(i).collide(system.get(j)); and this edits the velocities etc.
My problem is, Eclipse wants me to have a method in each of the Circle, Boundary... classes called collide(Item itemName) but by doing this the compiler wouldn't be able to treat each type of item differently.
I currently have different methods in the Circle, Boundary... classes like:
collide(Circle c){..}
collide(Boundary b){..}
collide(Photon p){..}
But the compiler wants a general collide(Item i) method.
How can I satisfy the compiler but still treat collisions with different types differently using inheritance the way I have?

You should Override collide(Item i) for each of subclasses. You could check the type of item in each implementation, for instance, in your Photon class :
#Override
public void collide(Item item) {
if (item instanceof Photon) {
// implement collision of this with (Photon) item
} else if ... {
// I wonder how collision of Photon with Circle would look like :)
}
}
This is quite similar approach to Overriding Object's equals method for new types.

You can still use collide(Item i)
But if you want the method to act differently for each super class you can do this:
public void collide(Item i) {
if(i instanceof Circle) {
//do something for a circle
} else if(i instanceof Photon) {
//do something for a photon
} else if(i instanceof Boundary) {
//do something for a boundary
}
}

You can simply keep collide(Item b){..} or Something like collide(<? extends Item> b){..}. You can introduce generics concept here if you are going to pass subtypes also.
This will give more info about it. http://www.thejavageek.com/tag/generics/

Related

Java: Most efficient way of calling different methods depending on the parameter type, which all share the same superclass

Consider the following:
There is an abstract class Collider and some more classes that extend this class e.g. RectCollider and CircleCollider.
Multiple instances of these are all in the same List<Collider> colliders.
Now, my question is how I should approach checking for collisions between these colliders while keeping compatability between them. For example, I want to check for collisions between a RectCollider and another RectCollider differently from checking a RectCollider and a CircleCollider.
My idea so far was using a method to check which types the colliders are of (via instanceof) and then calling different methods depending on the result:
public Collision getCollision(Collider a, Collider b) {
if(a instanceof RectCollider) {
if (b instanceof CircleCollider) {
return rectCircle(a, b);
}
else if (b instance of RectCollider) {
return rectRect(a, b);
}
}
else if(a instanceof CirlceCollider) {
if (b instanceof CircleCollider) {
return cirlceCircle(a, b);
}
else if (b instance of RectCollider) {
return rectCircle(b, a);
}
}
else {
return null;
}
}
The way this method is called at the moment:
getCollision(colliders.get(i), colliders.get(i+1));
However, I'm not sure whether this really is the fastest/best approach, since this method becomes overly complicated real fast when more Collider types are added.
This way, your method size scales quadratically when you add new subclasses. Whether you can simply this, depends on the methods you are calling (rectRect, rectCircle etc.).
Are all of these methods uncorrelated, or does each method with the same shape share a common behaviour? In the former case, you're out of luck. In the latter case, you might want to define this behaviour in the subclasses of Collider and add a general method that extracts this behaviour. This could then be of constant size, e.g.:
public Collision getCollision(Collider a, Collider b) {
Force f1 = a.getCollisionInfo();
Force f2 = b.getCollisionInfo();
return new Collision(f1, f2);
}
Regarding execution performance, it doesn't matter. The JVM optimizes it all for you.

Class Hierarchy and Setup

So I am trying to make a simple RPG-like text-based game to consolidate some of my studies, and I am wondering how the best way to implement this type of setup is:
Interface called Fighter > implemented by AbstractFighter > MagicFighter and StrengthFighter extend AbstractFighter. (Originally MagicFighter and StrengthFighter had their own interfaces with additional unique behaviours) but...
Now where it gets confusing is I want the player to be able to choose between these two types of Fighter, I then store this in a List(Fighter). So obviously the type I get back is always Fighter (it has to be as I dont know which implementation of Fighter the user will choose) and I can only call methods that are in the Fighter interface
One thing I could do is to write checks for what the player chose and downcast every time I need to call methods unique to the different Fighter implementations. But this would mean alot of repeated code, and sounds messy =/.
Another possibility is to run checks and add the user to a List(StengthFighter) or List(MagicFighter) based on their choice, but ultimately this just has the exact same problem as the previous 'solution'.
The final thing I can think of is to try and mirror each implementation of Fighter so that there is always a version of each behaviour for each. So for example
void regen(); in the Fighter interface and then implemented differently for StrengthFighter and MagicFighter (Magic fighter might regen mana, strength fighter might regen rage whenever he uses an attack() (which is another issue as due to ManaFighter needing to implement regen() it is obviously public, but the use of it within StrengthFighter would be private).
Anyway, you probably get the gist by now, so il save any more textwalling.
What it boils down to; is this a flaw in my implementation. Or is this just an inevitability with OO programming? I mean, at the end of the day, how can Java know what type the result needs to be (and therefore use its methods) if it is asking the user to make a decision that determines the type.
This is a rough class implementation based on interpretations of your question. Your original definition of having an interface and then an implementation and then the individual types feels complex. Instead, we want to work with individual Fighters and not representations of them.
class Fighter {
int hp;
void attack() {
}
void move() {
}
void regen() {
hp++;
}
}
class MagicFighter extends Fighter {
int mana;
#Override
void regen() {
mana++;
//we don't regen hp because we're magic-type.
}
}
class StrengthFighter extends Fighter {
int rage;
#Override
void attack() {
super.attack();
specialRegen();
}
void specialRegen() {
rage++;
}
#Override
void regen() {
// does nothing
}
void berserk() {
rage--;
}
}
In this case, we could store a list of Fighter
List<Fighter> fighters = new List<>();
When we want to create a new fighter, we would determine what the user wanted and add that to the list of fighters.
if (selection.equals("StrengthFighter")) {
Fighter fighter = new StrengthFighter();
fighters.add(fighter);
}
Then, we'd call all the methods as normal. Anything shared between the two classes would not be overridden, such as Fighter.move. Anything that doesn't work for only one type would be overridden, like StrengthFighter.regen. Anything that has special additional functionality for a specific type would implement the additional functionality and make a super call, like StrengthFighter.attack.
Basically, you have the right idea already, but basically, you want Fighter to do as much of the shared work as possible, and then implement individual actions based on the type behind the scenes. If something needs to be checked for type, it needs to be something unique to that type of Fighter, such as StrengthFighter.berserk.
This reduces the need to check types except when they really matter.
I think you have the only Fighter > FighterImpl. Other staff should be implemented separately: weapons, armor, abilities, etc...
On creation you grant the fighter with abilities + weapon (restricted by abilities) + perks. Then all fighters live in the same conditions.
interface Fighter {
int getSpeed(); // base fighter speed per time unit
Armor getArmor();
Weapon getWeapon();
Damage attack(Fighter enemy); // animate + apply damage
Position move();
List<Perks> getPerks();
List<Ability> getAbilities();
}
interface Weapon {
DamageType getDamageType();
int getDamage();
void animateHit(Fighter enemy);
}
abstract class AbstractWeapon implements Weapon {
...
}
abstract class MeleeWeapon extends AbstractWeapon {
...
}
abstract class MagicWeapon extends AbstractWeapon {
...
}

Java - alternative to instanceof?

I have a Shape superclass and a NestedShape subclass. The NestedShape subclass has an ArrayList ('ShapesList') of Shapes that are nested within it. I need to implement a 'contains' method for NestedShape. This method, when given a Shape object, should check whether the shape exists in the NestedShape's ShapeList. My implementation at the moment is very simple: just call the ArrayList .contains() method on ShapesList.
However, the 'contains' method I need to implement also has to check that for any NestedShape in the ShapesList, that shape's ShapeList also doesn't contain the shape that is being searched for. The obvious way to me of doing this is to use instanceof to check if each Shape in the ShapeList is a NestedShape. Then, I guess I'd recursively call my 'contains' method on it if it was a NestedShape. However, I'm not sure if this is a good way of doing this - I've heard that the use of instanceof is frowned upon (also, I'm not sure if my idea of using recursion would even work).
Could anyone suggest a better way of solving this problem?
Thanks :)
Use polymorphism:
public class Shape {
public boolean contains(Shape shape) {
return false;
}
}
public class NestedShape extends Shape {
private List<Shape> subShapes = new ArrayList<Shape>();
#Override
public boolean contains(Shape shape) {
if (subShapes.contains(shape)) {
return true;
}
for (Shape subShape : subShapes) {
if (subShape.contains(shape)) {
return true;
}
}
return false;
}
}
Two ideas:
Don't let NestedShape extend Shape, but handle them seperately.
Let all Shapes be 'nested'. With single shapes returning always false for contains().
If
the performance of the contains() method is your concern and
NestedShape are immutable meaning the list of nested Shape instances once set will never change
then I would suggest a slightly different approach.
Instead of recursively iterating though all the NestedShapes you can add a Set inside the Shape class that will store the references to all the NestedShape instances for which it is possible to access this Shape instance.

Casting and instance of or nearly empty interface?

I'm programming some kind of board game containing robots, items and such.
At one point, I need to get the energy value of a robot or an item that can have energy. The way this is programmed is that each robot and each item having energy have an EnergyContainer class as a field (to prevent code redundancy) and an energy Value class.
Now, basically, I call a method evaluate() that receives an Element. Element is an abstract class which robot and items extend. Not all elements have energycontainers. If possible, I need to call the getEnergyContainer on this element, but only if it is an element that has it of course.
I can think of a couple solutions: using a lot of instanceOf and then casting. So asking for example, if the element is instanceof robot, cast element to robot and call getEnergyContainer on the element. This has as clear disadvantage that I need to do this for every energy having subclass of element.
Second solution is defining an interface containing only a getEnergyContainer method and make all energy having classes implement this. The only purpose for this interface is then to facilitate the one method and it would be nearly empty.
Unless anybody has a better idea, what is the "best" solution? Nearly empty interfaces are used as Marker interfaces I think, but this it is one and only purpose so I'm a bit inclined against it.
If possible, I need to call the getEnergyContainer on this element, but only if it is an element that has it of course.
Why would you not want to call it on an element that doesn't have an energy container? If it doesn't have an energy container, either return a reference to some "null object" implementation of EnergyContainer, or return a null reference. It depends on what you want to do with it later - if you can easily implement some sort of "neutral" energy container, then the null object pattern is the simplest approach. Otherwise, just:
EnergyContainer container = element.getEnergyContainer();
if (container != null) {
// Use the container
}
There are no doubt those who would argue that this is in some senses "impure" - but it's almost certainly simpler than most alternatives.
The best solution would be to put the getEnergyContainer() method in one of the super classes of all energy containing elements the overriding this method in each elements class. You can make this method abstract to ensure its over-ridden. your super-class for this could be Element because you said: Element is an abstract class which robot and items extend.
Given your class hierarchy use composition with an Interface to provide default EnergyContainer behaviour
abstract class Element {
EnergyContainer ec = new EmptyEnergyContainer();
int getEnergyValue() {
getEnergyContainer().getValue();
}
EnergyContainer getEnergyContainer() {
return ec;
}
setEnergyContainer(EnergyContainer container) {
this.ec = container;
}
}
class Robot extends Element {
public Robot() {
this.ec = new ActiveEnergyContainer();
}
}
class Item extends Element{
public Item() {
this.ec = new ActiveEnergyContainer();
}
}
class Brick extends Element{
// will have a EmptyEnergyContainer by default
}
The Interface hierarchy for the EnergyContainer is like this
interface EnergyContainer {
int getValue();
setValue(int value);
}
class EmptyEnergyContainer implements EnergyContainer {
#Override
int getValue() {
return 0;
}
#Override
setValue(int val) {
throw Exception("Can not charge an empty container");
}
}
class ActiveEnergyContainer implements EnergyContainer {
int value;
#Override
int getValue() {
return 17 + 3; // calculate the value
}
#Override
setValue(int val) {
this.value = val // or do some funky calculation
}
}
At runtime you are able to set new EnergyContainer types for your objects. If you have multiple parent classes like Element then you will have to follow the same pattern of adding the default behaviour to the abstract parent and override as required.
Having the default behaviour return a sensible default value for getValue() will help you not have to use instanceof all over the place.
Potential improvements to this code would be to introduce
AbstractFactory pattern for creating the various EnergyContainer
variants
Including a hasEnergy() method to make your code more readable rather than checking for a value == 0
Make Element implement an Interface if other similar parent classes will include simlar methods

Why cast after an instanceOf?

In the example below (from my coursepack), we want to give to the Square instance c1 the reference of some other object p1, but only if those 2 are of compatible types.
if (p1 instanceof Square) {c1 = (Square) p1;}
What I don't understand here is that we first check that p1 is indeed a Square, and then we still cast it. If it's a Square, why cast?
I suspect the answer lies in the distinction between apparent and actual types, but I'm confused nonetheless...
Edit:
How would the compiler deal with:
if (p1 instanceof Square) {c1 = p1;}
Edit2:
Is the issue that instanceof checks for the actual type rather than the apparent type? And then that the cast changes the apparent type?
Old code will not work correctly
The implied cast feature is justified after all but we have trouble to implement this FR to java because of backward-compatibility.
See this:
public class A {
public static void draw(Square s){...} // with implied cast
public static void draw(Object o){...} // without implied cast
public static void main(String[] args) {
final Object foo = new Square();
if (foo instanceof Square) {
draw(foo);
}
}
}
The current JDK would compile the usage of the second declared method.
If we implement this FR in java, it would compile to use the first method!
🔴 JDK 14
We finally implemented this feature in JDK 14. As you might have noticed you can declare a new variable within the instanceof-linkage. This new variable has been defined by the value of a automatically downcast to the specified type.
if (any instanceof String s) {
System.out.println(s);
}
Keep in mind, you could always assign an instance of Square to a type higher up the inheritance chain. You may then want to cast the less specific type to the more specific type, in which case you need to be sure that your cast is valid:
Object p1 = new Square();
Square c1;
if(p1 instanceof Square)
c1 = (Square) p1;
The compiler does not infer that since you are in the block, you have done a successful check for the type of the object. An explicit cast is still required to tell the compiler that you wish to reference the object as a different type.
if (p1 instanceof Square) {
// if we are in here, we (programmer) know it's an instance of Square
// Here, we explicitly tell the compiler that p1 is a Square
c1 = (Square) p1;
}
In C# you can do the check and the cast in 1 call:
c1 = p1 as Square;
This will cast p1 to a Square, and if the cast fails, c1 will be set to null.
Just to provide an update on this, Java 14 now provides pattern matching for instanceof, this allows you to check and cast in one fell swoop.
This (old way):
void outputValue(Object obj) {
if (obj instanceof String) { // Compare
String aString = (String) obj; // New variable & explicit casting
System.out.println(aString.toUpperCase()); // Access member
}
}
Can be simplified to this:
void outputValue(Object obj) {
if (obj instanceof String aString) { // Compare and cast (if true)
System.out.println(aString.toUpperCase()); // Access member
}
}
There's a difference between measuring if some object will fit in a box, and actually putting it in the box. instanceof is the former, and casting is the latter.
Because this particular syntactic sugar is not yet added to the language. I think it was proposed for Java 7, but it doesn't seem to have entered project coin
E.g. If you hand over p1 as of type Object, the compiler wouldn't know that it is in fact an instance of Square, so that Methods etc. wouldn't be accessible. The if simply checks for a certain type to return true/false, but that doesn't change the type of the variable p1.
The test is done to prevent from ClassCastExceptions at runtime:
Square c1 = null;
if (p1 instanceof Square) {
c1 = (Square) p1;
} else {
// we have a p1 that is not a subclass of Square
}
If you're absolutly positive that p1 is a Square, then you don't have to test. But leave this to private methods...
The variable p1 has whatever type it started with - let's say Shape. p1 is a Shape, and only a Shape, no matter that its current contents happen to be a Square. You can call - let's say - side() on a Square, but not on a Shape. So long as you are identifying the entity in question via the variable p1, whose type is Shape, you can't call side() on it, because of the type of the variable. The way Java's type system works, if you can call p1.side() when you happen to know it's a Square, you can always call p1.side(). But p1 can hold not just Square Shapes, but also (say) Circle Shapes, and it would be an error to call p1.side() when p1 held a Circle. So you need another variable to represent the Shape which you happen to know is a Square, a variable whose type is Square. That's why the cast is necessary.
Not to be obnoxious, but you have to tell the compiler what you want to do because the alternative would be for it to guess what you're trying to do. Sure, you might think, "If I'm checking the type of an object, OBVIOUSLY that must mean that I want to cast it to that type." But who says? Maybe that's what you're up to and maybe it isn't.
Sure, in a simple case like
if (x instanceof Integer)
{
Integer ix=(Integer) x;
...
My intent is pretty obvious. Or is it? Maybe what I really want is:
if (x instanceof Integer || x instanceof Double)
{
Number n=(Number) x;
... work with n ...
Or what if I wrote:
if (x instanceof Integer || x instanceof String)
What would you expect the compiler to do next? What type should it assume for x?
RE the comments that instanceof is obsolete or otherwise a bad idea: It can certainly be mis-used. I recently worked on a program where the original author created six classes that all turned out to be pages and pages long, but identical to each other, and the only apparent reason for having them was so he could say "x instanceof classA" versus "x instanceof classB", etc. That is, he used the class as a type flag. It would have been better to just have one class and add an enum for the various types. But there are also plenty of very good uses. Perhaps the most obvious is something like:
public MyClass
{
int foo;
String bar;
public boolean equals(Object othat)
{
if (!(othat instanceof MyClass))
return false;
MyClass that=(MyClass) othat;
return this.foo==that.foo && this.bar.equals(that.bar);
}
... etc ...
}
How would you do that without using instanceof? You could make the parameter be of type MyClass instead of Object. But then there's be no way to even call it with a generic Object, which could be highly desirable in many cases. Indeed, maybe I want a collection to include, say, both Strings and Integers, and I want comparisons of unlike types to simply return false.
As Leroy mentioned, Java 14 introduces pattern matching for instanceof. So, you can combine both instanceof check and typecast altogether in a single expression:
if (p1 instanceof Square) {
c1 = (Square) p1;
}
can be rewritten as
if (p1 instanceof Square c1) {
// use c1
}
This feature is finalized in Java 16 (JEP 394). For the below versions, refer this link to enable this preview feature from IDEs such as IntelliJ, Eclipse, and STS.
If c1 is declared as a type of Square then casting is required. If it is a declared as an Object then casting is not needed.

Categories

Resources