Nested classes, best approach?

So, long story short, I’m making a neural network. Basically, I currently have one big 2D irregular array of Neuron objects (say, of the following shape or similar: {784, 32, 32, 10}), and I’ve just got the idea of turning those inner arrays into objects themselves. That way, I could store extra information about those arrays within them, along with all the Neuron objects they’re already storing. It would certainly give them more power, in the sense that I could move more of my code into the objects themselves, rather than doing all the important math in the draw function due to accessibility issues (such as, comparing which neuron returns the largest value; that’s something I currently have to do from the “outside”; but this way, I could just store this information inside the outer class).

So, my question is, how do I do this? I first thought to use nested classes, but I’ve soon found out that you can’t really access that inner class from the outside, so, I moved it out. Idk what to call it now, it’s like, the class exists outside of any other function or class, but is declared, initialized, and everything, from within a different class.

I have no idea if this is the recommended approach, or whether it’s good but I should still change something, or perhaps whether I should abolish the idea entirely and go back to my 2D array approach… heck, I don’t even know if I’ve coded it correctly, since this is the first time I’m trying to make a class within a class.

//the neurons are stored in "layers", in this case, I have 4 layer objects, storing 20, 32, 32 and 10 neuron objects
class Neuron {
  int I, L; //the neuron will know the index of its corresponding layer, and its own index within this layer
  Neuron(int index, int layer) {
    I = index;
    L = layer;
  }
  void doMath() { //test to see if things are working... no idea if this is prone to defects though
    println("Hello, I am neuron " + I + " of layer " + L);
  }
}

class Layer {
  Neuron[] neuron; //declare an array of neurons for each layer
  int size; //will store the size of this array
  Layer(int index, int size_) {
    size = size_;
    neuron = new Neuron[size]; //initialize the array
    for (int N = -1; ++N != size; ) {
      neuron[N] = new Neuron(N, index); //make a new neuron for each slot within the array, and give it its own index and the index of its "parent" class
    }
  }
  void doMath() {
    println(size); //another test
  }
}

int[] networkSetup = {20, 32, 32, 10};
Layer[] network = new Layer[networkSetup.length];

void setup() {
  //again, for each slot in the network array, create a new layer object and give it its index, but also the size of the neuron array it will then have to create itself
  for (int L = -1; ++L != network.length; ) network[L] = new Layer(L, networkSetup[L]);
  for (Layer L : network) {
    L.doMath();
    for (Neuron N : L.neuron) N.doMath(); //this piece of code is what breaks if I use the nested class approach
  }
}

void draw() {
  
}

So again, is this a good approach? Should I change anything? Are there any disadvantages of using this instead of the 2D array approach that I should know of beforehand?

You’re doing nothing wrong, and as you’ve found out, it’s fine to define one class inside another - but only so long as all references to the enclosed class remain inside the outer, containing class.

The problem with trying to define a Neuron inside the Layer is that, when you loop over the layer’s neurons, that loop needs to know what a Neuron is!

But this loop can also be moves into the Layer class easily with just a tad more effort. Consider:


class Layer {
  class Neuron {
    int I, L; //the neuron will know the index of its corresponding layer, and its own index within this layer
    Neuron(int index, int layer) {
      I = index;
      L = layer;
    }
    void doMath() { //test to see if things are working... no idea if this is prone to defects though
      println("Hello, I am neuron " + I + " of layer " + L);
    }
  }

  Neuron[] neuron; //declare an array of neurons for each layer
  int size; //will store the size of this array
  Layer(int index, int size_) {
    size = size_;
    neuron = new Neuron[size]; //initialize the array
    for (int N = -1; ++N != size; ) {
      neuron[N] = new Neuron(N, index); //make a new neuron for each slot within the array, and give it its own index and the index of its "parent" class
    }
  }
  void doMath() {
    println(size); //another test
  }
  void doNeuronMath(){
        for (Neuron N : neuron) N.doMath(); // Now the Neuron class is ONLY used inside the Layer class!
  } // End of doNeuronMath()
} // End of layer class.

int[] networkSetup = {20, 32, 32, 10};
Layer[] network = new Layer[networkSetup.length];

void setup() {
  //again, for each slot in the network array, create a new layer object and give it its index, but also the size of the neuron array it will then have to create itself
  for (int L = -1; ++L != network.length; ) network[L] = new Layer(L, networkSetup[L]);
  for (Layer L : network) {
    L.doMath();
    L.doNeuronMath(); // This is a new function!
  }
}

void draw() {
  
}

Untested code, YMMV.

1 Like

And if I want to iterate over it as if I were iterating over a 2D array, I’d have to do it like this?

for (Layer L : network) for (Layer.Neuron N : L.neuron) N.doMath();

It doesn’t seem to be throwing any errors, which is good.