Static methods

edited April 2017 in Questions about Code
static class MyNumber{
int no = 0;
static int max= -9999999;
static int min = 9999999;

MyNumber(int n){
  no = n;
  if (no>max){ max = no; }
  if (no<min){min = no; }
}

static void report(){
  println("Min: "+min+", Max: "+max);  
}

static float randomNo(){
  return random(min, max);  

}

In the above code, I get the error Cannot make a static reference to the non-static method random(float, float) from the type PApplet. Why is that so? I wish to keep a list of min and max numbers for all instances of MyNumber, and hope to operate on those values via a static method.

Answers

  • edited April 2017 Answer ✓
    • PApplet::random() method isn't static!
    • In order to access it, we need to prefix it w/ a PApplet's reference.
    • Your options then:
    1. Make your static class demand a PApplet's reference. Constructor is the best place for it btW.
    2. Remove static from your class, turning it a PApplet's inner class.
    3. Use Math::random() instead or instantiate the Random class just for your MyNumber.

    https://Processing.org/reference/random_.html
    http://Docs.Oracle.com/javase/8/docs/api/java/lang/Math.html#random--
    http://Docs.Oracle.com/javase/8/docs/api/java/util/Random.html

  • I attempted method 1:

    static class MyNumber{
    int no = 0;
    static int max= -9999999;
    static int min = 9999999;
    static PApplet pa;
    
    
    MyNumber(PApplet p, int n){
      no = n;
      pa = p;
      if (no>max){ max = no; }
      if (no<min){min = no; }
    }
    
    static void report(){
      println("Min: "+min+", Max: "+max);  
    }
    
    static float randomNo(){
      return pa.random(min, max);  
    
    }
    

    Works well except I need to have at least one MyNumberinstances declared before I can run MyNumber.randomNo, else pa will not be initalised and I will get a NPE.

    I doubt I will run into a situation where I will call a static method without initialising any instances, but I shall just ask for learning purposes: Is there a way around that?

    Remove static from your class, turning it a PApplet's inner class.

    Can you elaborate? I'm clueless what that means. Does it mean I extend PApplet?

  • edited April 2017

    Can you elaborate? I'm clueless what that means.

    I've meant about not declaring your class as static.

    Works, well, except I need to have at least one MyNumber instance...
    Is there a way around that?

    Given your field pa is static, you can initialize it directly within setup(): MyNumber.pa = this;

    However, I don't get why you're declaring your fields static.
    Doing so you can't individualize instances of your class MyNumber.
    They'll all share fields min, max & pa. Only field no is created for each instance of it. :-@

    Just did another similar class demoing how to do it w/o static fields: O:-)

        // https://forum.processing.org/two/discussion/21780/static-methods#Item_3
        // 2017-Apr-03
        
        final ConstrainedNumber myNum = new ConstrainedNumber(this, 0);
        
        void setup() {
          println(myNum);
          println(myNum.setLimits(-10, 21).randomNum());
          println(myNum);
          exit();
        }
        
        static class ConstrainedNumber {
          final PApplet p;
          int num, minNum = MIN_INT, maxNum = MAX_INT;
        
          ConstrainedNumber(final PApplet pa, final int n) {
            p = pa;
            setNum(n);
          }
        
          ConstrainedNumber setLimits(final int low, final int high) {
            minNum = low;
            maxNum = high;
            return this;
          }
        
          int setNum(final int n) {
            return num = constrain(n, minNum, maxNum);
          }
        
          int randomNum() {
            return num = (int) p.random(minNum, maxNum);
          }
        
          @Override String toString() {
            return "num: " + num + "\tlow: " + minNum + "\thigh: " + maxNum;
          }
        }
    
  • Why are you using static classes and static members? Why not just use inner classes?

  • edited April 2017

    They'll all share fields min, max & pa. Only field no is created for each instance of it.


    Why are you using static classes and static members?

    I wanted to use static minand maxto keep track of the smallest and largest values across all the instances of MyNumber. Meaning to say, minand maxare not set by the user, they record the smallest and largest number among all instances of MyNumber. I was also hoping to be able to do some operations like generate a random number from among the minand max, without making an instance of MyNumber.

    I will be building up from this class and integrate it into my battery data class where I want to keep track of the min and max values across each batteries to draw the graph.

      ConstrainedNumber setLimits(final int low, final int high) {
        minNum = low;
        maxNum = high;
        return this;
      }
    

    Interesting to see how you return an instance of ConstrainedNumberso you can set randomNumin the same line.

    Why not just use inner classes?

    I am not familiar with inner classes in this sense. From I know, inner classes are classes within a class. I guess since all classes in Processing are part of one instances of PApplet, just do not use static? I was hoping to use static because I want min and max to be shared among all instances of MyNumber, so I can know the smallest and largest number among all MyNumber instances I created.

  • edited April 2017

    Interesting to see how you return an instance of ConstrainedNumber so you can set randomNum() in the same line.

    If we return this, i.e. the same object which invoked the method, we turn it into a chainable method.

    From I know, inner classes are classes within a class.

    Actually Java's stricter name for such is nested class. ~O)
    Inner class is a more specific name for when the nested class is non-static as well. ;)
    That is, all inner classes are nested too. But not all nested classes are inner 1s! :P

  • edited April 2017 Answer ✓

    I will be building up from this class and integrate it into my battery data class where I want to keep track of the min and max values across each batteries to draw the graph.

    Now I understand why you wanted static fields as well. :\">
    Made some tweaks and tests below. Take a look: B-)

    // https://forum.processing.org/two/discussion/21780/static-methods#Item_6
    // 2017-Apr-04
    
    MyNumber num1, num2;
    
    void setup() {
      MyNumber.p = this;
      println(MyNumber.report());
    
      println("num1:\t", num1 = new MyNumber(10));
    
      MyNumber.setLimits(-50, 91);
      println("num2:\t", num2 = new MyNumber(MyNumber.randomNum()));
    
      println("num1:\t", num1.setRandomNum());
      println("num1:\t", num1);
    
      println("num2:\t", num2.setNum(832));
    
      println(MyNumber.report());
      exit();
    }
    
    static class MyNumber {
      static PApplet p;
      static int lowest = MAX_INT, highest = MIN_INT;
      int num;
    
      MyNumber(final int n) {
        setNum(n);
      }
    
      MyNumber setNum(final int n) {
        lowest = min(num = n, lowest);
        highest = max(n, highest);
        return this;
      }
    
      static final void setLimits(final int low, final int high) {
        lowest  = low;
        highest = high;
      }
    
      static final int randomNum() {
        return (int) p.random(lowest, highest);
      }
    
      int setRandomNum() {
        return num = randomNum();
      }
    
      static final String report() {
        return "low: " + lowest + "\thigh: " + highest;
      }
    
      @Override String toString() {
        return "num: " + num + TAB + report();
      }
    }
    
  • Answer ✓

    It seems that random() is the only mathematical function that is not declared static in PApplet how ridiculus.

    This is a simple modification of your class avoiding the need for an instance of PApplet to get a random number.

    static class MyNumber {
      static int max= -Integer.MAX_VALUE;
      static int min = Integer.MAX_VALUE;
    
      int no;
    
      // Hide the default constructor
      private MyNumber() {
      }
    
      static void report() {
        if (min == Integer.MAX_VALUE)
          println("No numbers created yet");
        else
          println("Range is " + min + " to " + max + " inclusive.");
      }
    
      public static float randomNo() {
        return (int) Math.random() * (max - min) + min;
      }
    
      public MyNumber(int n) {
        no = n;
        if (n < min) min = n;
        if (n > max) max = n;
      }
    }
    
  • edited April 2017

    It seems that random() is the only mathematical function that is not declared static in PApplet. How ridiculous!

    In order to keep a randomSeed(): https://Processing.org/reference/randomSeed_.html
    PApplet::random() gotta be non-static, keeping an instance of Random as well! :>
    There's no shame on that. Don't be too prejudice about it. :-\"

  • PApplet creates an instance variable of called internalRandom of type java.util.Random which is used by all methods requiring random numbers. If this was declared as a static variable and then all these methods including randomSeed() could also be static.

    Perhaps 'rediculus' was overstating it a bit :D , but I don't see a problem with having these as static methods in the same way as all the other mathematical methods are static e.g. min, max, sin, cos, tan, abs, map, constrain ... etc etc etc.

    There maybe a reason but I cannot think of a good one.

  • edited April 2017

    If this was declared as a static variable and then all these methods including randomSeed() could also be static.

    ... but I don't see a problem with having these as static methods

    That'd be very bad for PApplet threaded multi-windows. [-X
    B/c all instances of PApplet would have 1 shareable "seed" only! :-@

    The latest PApplet instance to call randomSeed() would determine the "seed" for all the others! :O)

    Even though Random is thread-safe, concurrent calls to the same instance of it would cause contention and consequent poor performance: :-SS
    http://Docs.Oracle.com/javase/8/docs/api/java/util/Random.html

  • OK good point, I was not aware of that, but I promise to remember it for the next time I use PApplet threaded windows ;)

Sign In or Register to comment.