catch variable from class Object when this one is a instanceof :

I try to write generic method to pass different class by this one. My idea is test the obect to see if it is an instance of my target class, but when I'm testing positively the nature of class, I cannot catch the method or var of this class :

Mother mother = new Mother(1) ;
ArrayList<Mother> list_mother = new ArrayList<Mother>() ;

void setup() {
  list_mother.add(mother) ;

  method_list(list_mother) ;
}

void method_list(ArrayList list) {
  for(Object obj : list) {
    if(obj instanceof Mother) {
      println("list Mother") ;
      println(obj.x) ;
    }
  }
}

class Mother {
  int x ;
  Mother(int x) {
    this.x = x ;
  }
}

Answers

  • edited July 2016 Answer ✓

    In line 11 obj is declared as an Object this class does not have an attribute called x so when you come to use it in line 14 it doesn't work. The trick is to cast the variable obf to Mother

    CHange line 14 to

    println( ((Mother)obj).x ) ;

    Or even better do this

    void method_list(ArrayList list) {
      for(Object obj : list) {
        if(obj instanceof Mother) {
          Mother m = (Mother) obj;
          println("list Mother") ;
          println( m.x ) ;
        }
      }
    }
    
  • Whaouuu, it's so simple...Sure alone I take one week to find it :) thx a lot for the trick.

  • edited July 2016

    A more refined example: :bz

    // forum.processing.org/two/discussion/17617/
    // catch-variable-from-class-object-when-this-one-is-a-instanceof
    
    // GoToLoop (2016-Jul-22)
    
    import java.util.List;
    final List<Parent> mothers = new ArrayList<Parent>();
    
    void setup() {
      mothers.add(new Mother(1));
      mothers.add(new Father(-3));
    
      listParentValues(mothers);
      exit();
    }
    
    static <P extends Parent> List<P> listParentValues(final List<P> parents) {
      for (final P p : parents)
        if (p instanceof Mother)  println("Mother: " + ( (Mother) p ).x);
        else                      println("Father: " + ( (Father) p ).y);
      return parents;
    }
    
    static interface Parent {
    }
    
    static class Mother implements Parent {
      final int x;
    
      Mother(int xx) {
        x = xx;
      }
    }
    
    static class Father implements Parent {
      final int y;
    
      Father(int yy) {
        y = yy;
      }
    }
    
  • Answer ✓

    Generally it is considered bad practice to use the instanceof operator. Using an interface is one way to avoid its use.

    ArrayList<Parent> parents = new ArrayList<Parent>();
    
    void setup() {
      parents.add(new Mother(25));
      parents.add(new Mother(40));
      parents.add(new Father(65));
    
      listParentValues(parents);
      exit();
    }
    
    void listParentValues(ArrayList<Parent> parents) {
      for (Parent p : parents)
        println(p.getClass().getSimpleName() + ":\t" + p.getAge());
    }
    
    interface Parent {
      int getAge();
    }
    
    class Mother implements Parent {
      int age;
    
      Mother(int a) {
        age = a;
      }
    
      int getAge() {
        return age < 30 ? 30 : 30 + round(0.6 * (age - 30));
      }
    }
    
    class Father implements Parent {
      int age;
    
      Father(int a) {
        age = a;
      }
    
      int getAge() {
        return age;
      }
    }
    
  • edited July 2016

    That's sound very good to can use the interface name to create a list. Big step for me. But if I create few extends class of Mother? I must still use instanceof

    Mother mother = new Mother(1) ;
        Child child = new Child(3,2) ;
        ArrayList<Agent> list = new ArrayList<Agent>() ;
    
        void setup() {
          list.add(mother) ;
          list.add(child) ;
          print_list(list) ;
          exit() ;
        }
    
    
        void print_list(ArrayList<Agent> list_agent) {
          for(Agent a : list_agent) {
            println(a.get_x()) ;
            if(a instanceof Child) {
              Child c = (Child) a;
              println(c.get_y()) ;
            }
          }
        }
    
    
        interface Agent {
          int get_x()  ;
        }
    
        class Mother implements Agent {
          int x ;
          Mother(int x) {
            this.x = x ;
          }
    
          int get_x() {
            return x ;
          }
        }
    
        class Child extends Mother implements Agent {
          int y ;
          Child(int x, int y) {
            super(x) ;
            this.y = y ;
          }
    
          int get_x() {
            return x ;
          }
    
          int get_y() {
            return y ;
          }
        }
    
  • edited July 2016 Answer ✓

    Interface Agent is both a marker/label & a contractor.

    That is, any class which implements it or extends some class that does it already, is guaranteed to have the method get_x() therein.

    However, your subclass Child got an exclusive method called get_y(), which is outside Agent's contract.
    Therefore, in order to invoke get_y(), you're gonna need to cast it as (Child). #-o

  • @gotoloop I ask a question about instanceof because @quark say is not a good practice. there is an other way to cast Agent to Child whitout instanceof ?

  • edited July 2016

    Classic inheritance, which is based on extends keyword, is far from perfect. =((
    There are other approaches like composite inheritance and trait build classes, etc.

    Quickest dirty fix is to add get_y() to interface Agent.

    But as you may be guessing by now, that'd oblige class Mother to implement that as well, even though it doesn't need that method, forcing all classes implementing interface Agent to increase their "baggage" weight unnecessarily. :-@

    interface Agent {
      int ABSENCE = MIN_INT;  // value representing absence.
    
      int getX();
      int getY(); // extra method!
    }
    
    class Mother implements Agent {
      int x;
    
      Mother(int xx) {
        x = xx;
      }
    
      @ Override int getX() {
        return x;
      }
    
      @ Override int getY() { // Obliged to comply w/ Agent's contract!
        return ABSENCE;
      }
    }
    
    static <P extends Agent> List<P> listAgentValues(final List<P> agents) {
      for (final P p : parents) {
        print("x: " + p.getX()); // both Mother & Child got method getX().
    
        int y = p.getY();
        if (y != p.ABSENCE)  print(", y: " + y); // only print if it's valid!
    
        println();
      }
    }
    
  • Thx a lot for all precious informations about interface, instanceof, implements...

Sign In or Register to comment.