How to create an array of different classes

edited May 2016 in How To...

firstly is this possible?

I am writing a program that has a bunch of different visualisations written in classes and I want the program to select a different random visualisation based on a timer. Furthermore I need the code to select slight variations within each visualisation once it is playing from a group. I assumed loading the classes into an array and selecting which one to use was the answer but I'm starting to think this is not the case.

Any pointers would be much appreciated, I'm not particularly clued up on how to use classes n objects beyond the basics.

Cheers Rich

Tagged:

Answers

    • Are you using more than 1 datatype class for those visualizations?
    • If that's the case, all of them needs to have a common "ancestor" in order to be stored in some container.
    • For example you can make an empty interface called Visual and have all those classes implements that.
  • edited August 2015

    Yea I think there are multiple data types. They are all pretty different.

    What do you mean by an empty interface? I started to have a look at nested classes and got totally lost!

    this is just two of them...

    class Scroller {
      int im;
      void happen(float speed, int wait) {
        ///// TIMED EVENT ////
        ///// check the difference between now and the previously stored time is greater than the wait interval
        if (millis()/1000 - time >= wait) {
          im +=1;            //// DO YOUR THANG ////
          time = millis()/1000;  //// also update the stored time
          if (im > 2) im = 0;   ////// NUMBER OF IMAGES IN ARRAY ////
        }
        // Scale the image so that it matches the width of the window
        int imHeight = images[im].height * width / images[im].width;
        // Scroll down slowly, and wrap around
        float y = (millis() * -speed) % imHeight;
        // Use two copies of the image, so it seems to repeat infinitely  
        image(images[im], 0, y, width, imHeight);
        image(images[im], 0, y + imHeight, width, imHeight);
      }
    }
    
    class Boxes {
      int pos, h, g, f;
    
      void pulse() {    //////// SINGLE BOX PULSING //////
        rectMode(CENTER);
        fill(c, a);
        if ( beat.isOnset() ) {
          pos = int(random(6)); 
          g = int(random(3));
          f = int(random(3, 6));
          h = int(random(6));
          if ( h == 0)fill(flash, a);
          a = 60;
        }
        a *= 1.05;
        if (a > 360) a = 100;
      }
      void flash() {    //////// SINGLE BOX PULSING //////
        rectMode(CENTER);
        fill(c, a);
        if ( beat.isOnset() ) {
          pos = int(random(6)); 
          g = int(random(3));
          f = int(random(3, 6));
          h = int(random(6));
          if ( h == 0)fill(flash, a);
          a = 360;
        }
        a *= 0.98;
        if (a < 60) a = 60;
      }
      void one() {            //////// SINGLE BOX /////
        PVector v = cor[pos];
        rect(v.x, v.y, 20, 20);
      }
      void two() {              //////// DOUBLE OPPOSITES  //////
        PVector v = cor[g];
        PVector w = cor[g+5-2];
        rect(v.x, v.y, 20, 20);
        rect(w.x, w.y, 20, 20);
      }
      void three() {              //////// DOUBLE RANDOM  //////
        PVector v = cor[g];
        PVector w = cor[f];
        rect(v.x, v.y, 20, 20);
        rect(w.x, w.y, 20, 20);
      }
      void mid() {              //////// DOUBLE MIDDLE  //////
        rect(cor[1].x, cor[1].y, 20, 20);
        rect(cor[4].x, cor[4].y, 20, 20);
      }
    }
    
  • Thats similar to what im doing currently, each visualisation, which started as a separate sketch is a class in its own tab. I was hoping for a way to have the program select between them using an array but maybe its better to just use a number of if(....) commands like in the link.

    I currently have thousands of lines of code we have been controlling with a midi pad and now need to make intelligent enough to run on its own.... which turns out to be really tough haha!

  • By empty interface I've meant it literally:

    interface Visual {
    }
    

    Then you can make the classes you wanna store in the same container implements that:

    class Scroller implements Visual {
    }
    
    class Box implements Visual {
    }
    

    Something like this:

    static final int QTY = 2;
    final Visual[] visuals = new Visual[QTY];
    
    void setup() {
      visuals[0] = new Box();
      visuals[1] = new Scroller();
      exit();
    }
    
    interface Visual {
    }
    
    class Scroller implements Visual {
    }
    
    class Box implements Visual {
    }
    
  • and then....?

    currentVisuals = 1;
    
    visuals[1].run();
    

    ?

  • Since all classes ultimately inherit from Java's Object class then you can use an Object collection (e.g. array or list) to store objects of any type.

    The only restriction is that you when you retrieve an object an object from the collection you must see what class it is and cast it appropriately. See the code below.

    class One {
      void doOne() {
        println("One");
      }
    }
    
    class Two {
      void doTwo() {
        println("Two");
      }
    }
    
    ArrayList<Object> objects = new ArrayList<Object>();
    
    void setup() {
      objects.add(new One());
      objects.add(new Two());
      for (Object o : objects) {
        if (o instanceof One) {
          ((One)o).doOne();
        } else if (o instanceof Two) {
          ((Two)o).doTwo();
        }
      }
    }
    

    This is not recommended for regular use but is useful if you want to simulate dynamic data typing.

    For normal use Java introduced typed collections (generics) to avoid having to test and cast objects.

  • Instead of an empty interface, I would make a real one.
    What all these objects have in common? Most likely they have something like a display() method, called when we want to show them.
    Thus, the interface is significant, and offers an uniform way of handling them.

    I have an example at https://github.com/PhiLhoSoft/Processing/tree/master/_SmallPrograms/DrawingInSequence

    The code is old, before generics were supported in Processing, I use an untyped ArrayList but it should be typed with Drawer (as shown in the comment before the declaration).
    I should update the sketch...

  • amazing! this looks like the route i wona go. It's going to need a lot of reading up again... if anyone could quickly explain the way to extend and implement classes that would be ace. I find the info in the processing reference a bit lacking if you don't understand everything!

    At the moment the classes don't have too much in common but I am adding more functions as I get my head around the code. I've been producing visuals for a year now but with no time to code it "properly" so everything is a bit cobbled together.

    Our next event is in a fortnight so there may not be time to get it all sorted but this a long way to helping me understand where to go next.

    I can upload my full program if that would help you see whats going on and what needs to go where for the instances and classes...

  • for basic java language concepts then you can just use the java documentation:

    https://docs.oracle.com/javase/tutorial/java/IandI/index.html

  • Updated the sketch to properly use generics...

    Interfaces are kind of blueprint: they tell that any class implementing them must define the methods they have.
    The advantage is that you can make a collection typed on that interface, where you can put any class that implement it.
    And since the class must implement these methods, you are sure you can call them after getting them out of the collection.

  • To add on all the above. I used to have things like (out of my head):

    interface Mode {
        void enter();
        void draw();
        void exit();
    
        void keyPressed(char key);
        void mousePressed();
        // etc.
    
    }
    
    class A implements Mode { ... }
    class B implements Mode { ... }
    
    
    Mode currentMode;
    
    void setup() {
        ...
        currentMode = a; 
    }
    
    void draw() {
       currentMode.draw();
    }
    
    void keyPressed() {
        if (key == '1') {
           changeMode(a);
        }
        else if (key == '2') {
           changeMode(b);
        }
        else {
           currentMode.keyPressed(key);
        }
    }
    
    void mousePressed() {
        currentMode.mousePressed();
    }
    
Sign In or Register to comment.