subclass elements from an arraylist won't use the overriden method in Java -


i have arraylist class (piece) want pick items subclass (miner , bomb). however, when pick items use methods of super class (piece), , not it's subclasses.

since arraylist<pieces> contain several subclass objects of pieces, not possible define more specific class arraylist. possible pick elements arraylist , still use methods subclasses?

(i found little hard find solution simple problem. searched overriding, arraylist, methods along other things, couldn't find it. if obvious found, i'd know found it.)

class main:

import java.util.arraylist; public class main {      public static void main(string[] args) {         arraylist<piece> piecelist = new arraylist<>();         piecelist.add(new miner());         piecelist.add(new bomb());          // create new classes test candefeat         if (new miner().candefeat(new bomb())) {             system.out.println("yes! line printed.");         }          system.out.println();          // test candefeat pieces piecelist         if (piecelist.get(0).candefeat(piecelist.get(1))) {                system.out.println("no, line not printed");         }      } } 

class piece:

public abstract class piece {      public boolean candefeat(piece opponent) {         return false;     } } 

class miner:

public class miner extends piece {      public boolean candefeat(bomb opponent) {         return true;     }  } 

class bomb:

public class bomb extends piece {  } 

the why of easy:

  1. your miner doesn't override candefeat(piece), adds new method signature candefeat(bomb).

  2. in code piecelist.get(0).candefeat(piecelist.get(1)), compiler has work type piece, , resolves piece#candefeat(piece).

the what instead more tricky.

i suggest kinds of pieces can defeat other kinds of pieces isn't attribute of each piece; 1 thing, brittle if change rules.

instead, @ alternatives like:

  • perhaps each piece can have strength level, higher strength means piece can defeat piece lower strength. (example below.)

  • you have battlelogic class can compare types of pieces determine outcome, either work strength per above, or type using instanceof, etc. normally, when reach instanceof need stop , think you're doing , whether it's right tool job (it isn't), may right tool this job. advantage battlelogic class none of pieces knows other pieces; instead, have 1 thing understands game whole , how pieces rank when fight. (example below.)

if want each piece know other types of pieces can defeat, can that, think tend lead unmaintainable mess. 2 ways come mind:

  • having list of types can defeat. (example below.)

  • using reflection achieve trying originally. (example below.)

here's strength suggestion in code:

import java.util.arraylist;  class piece {      private int strength;      public piece(int strength) {         this.strength = strength;     }      public int getstrength() {         return this.strength;     }      public boolean candefeat(piece opponent) {         return this.getstrength() > opponent.getstrength();     } }  class miner extends piece {      public miner() {         super(10);     } }  class bomb extends piece {     public bomb() {         super(5);     } }  public class main {      public static void main(string[] args) {         arraylist<piece> piecelist = new arraylist<>();         piecelist.add(new miner());         piecelist.add(new bomb());          // create new classes test candefeat         if (new miner().candefeat(new bomb())) {             system.out.println("yes! line printed.");         }          system.out.println();          // test candefeat pieces piecelist         if (piecelist.get(0).candefeat(piecelist.get(1))) {             system.out.println("yes! line printed");         }      } } 

and battlelogic suggestion in code:

import java.util.arraylist;  abstract class piece { }  class miner extends piece { }  class bomb extends piece { }  class battlelogic {      /**      * battle between 2 pieces.      *      * @param     first piece      * @param   b   second piece      * @return  0 tie, negative number if beats b, or positive number if b beats      */     public static int battle(piece a, piece b) {         if (a instanceof miner && b instanceof bomb) {             return -1;         }         // ...further tests here...         return 0;     }  }  public class main {      public static void main(string[] args) {         arraylist<piece> piecelist = new arraylist<>();         piecelist.add(new miner());         piecelist.add(new bomb());          // create new classes test candefeat         if (battlelogic.battle(new miner(), new bomb()) < 0) {             system.out.println("yes! line printed.");         }          system.out.println();          // test candefeat pieces piecelist         if (battlelogic.battle(piecelist.get(0), piecelist.get(1)) < 0) {             system.out.println("yes! line printed");         }      } } 

here's third suggestion, having each type of piece know pieces can defeat, in case. again, though, don't suggest this; think having pieces know each other going maintenance problem:

// not recommended import java.util.list; import java.util.arraylist;  abstract class piece {     private list<class> idefeat;      public piece(class... defeats) {         this.idefeat = new arraylist<class>();         (class c : defeats) {             this.idefeat.add(c);         }     }      public boolean candefeat(piece piece) {         return this.idefeat.contains(piece.getclass());     } }  class bomb extends piece { }  class miner extends piece {      public miner() {         super(bomb.class);     } }  public class main {      public static void main(string[] args) {         arraylist<piece> piecelist = new arraylist<>();         piecelist.add(new miner());         piecelist.add(new bomb());          // create new classes test candefeat         if (new miner().candefeat(new bomb())) {             system.out.println("yes! line printed.");         }          system.out.println();          // test candefeat pieces piecelist         if (piecelist.get(0).candefeat(piecelist.get(1))) {             system.out.println("yes! line printed");         }      } } 

or make list static if you're going have millions of pieces , memory issue; sketch.

and finally, way using reflection:

// not reall recommended import java.lang.reflect.method; import java.util.arraylist;  class piece {      public piece() {     }      private static method getmethodornull(class cls, string name, class... paramtypes) {         try {             return cls.getmethod(name, paramtypes);         }         catch (nosuchmethodexception nsme) {             return null;         }     }      public boolean candefeat(piece opponent) {         try {             class thisclass = this.getclass();             class oppclass = opponent.getclass();             method m = null;              while (oppclass != piece.class && (m = getmethodornull(thisclass, "candefeat", oppclass)) == null) {                 oppclass = oppclass.getsuperclass();             }             if (m != null) {                 return (boolean)m.invoke(this, opponent);             }             return false;         }         catch (exception iae) {             throw new runtimeexception("can't access method", iae);         }     } }  class miner extends piece {      public boolean candefeat(bomb b) {         return true;     }  }  class bomb extends piece { }  public class main {      public static void main(string[] args) {         arraylist<piece> piecelist = new arraylist<>();         piecelist.add(new miner());         piecelist.add(new bomb());          // create new classes test candefeat         if (new miner().candefeat(new bomb())) {             system.out.println("yes! line printed.");         }          system.out.println();          // test candefeat pieces piecelist         if (piecelist.get(0).candefeat(piecelist.get(1))) {             system.out.println("yes! line printed");         }      } } 

Comments

Popular posts from this blog

c# - Validate object ID from GET to POST -

node.js - Custom Model Validator SailsJS -

php - Find a regex to take part of Email -