Interface and classes


#1

I have several objects of different types which had to be stored in the same arrayList. I did this because most classes share similar functions.

ArrayList <Node> objectArray = new ArrayList();

With an interface

interface Node {
 void assignID(int ID);
 void Draw();
 int getColumn();
 int getRow();
 void setGridSize(int _gridSize);
 void turnLeft();
 void turnRight();
 void setPos(int Xpos, int Ypos);
 boolean getState();
 void setState(boolean state);
 int getID();
 void addSwitch(int switchID, boolean state);
 void triggered();
}

I can do the following:

for (int i = 0; i < objectArray.size(); i++) { 
      Node anyClass = objectArray.get(i);
      if(column == anyClass.getColumn() && row == anyClass.getRow()) { 
        index = i;

I can acces all members of any object of choise by getting the X and Y positions.

The problem I have with this is the following: In order to use a function of a certain object using the Node object. The function in question needs to be in the interface. If I add a function to the interface. All other classed need to have this function. That means that if i want to add one specific function to one class. I am forced to add dummy functions to all other classes as well. At first it was no problem but now my program grows it is getting annoying to keep making dummy functions.

How can I best work arround this? My only two demands are that I keep my arrayList with different object types and that I give certain objects unique functions. Do I have to something with inheritance??


#2

Would it be possible to have a method run() in the Node interface, and then have the “dummy” functions called within it? Something like:

class a implements Node {
  void run() {
    separatemethod1();
    separatemethod2();
  }
  void separatemethod1() {}
  void separatemethod2() {}
}

It also seems that some of functions in Node such as getPos() would be the same throughout every class implementing it, so you could consider using abstraction instead.


#3

Yes, you need to avoid adding dummy functions. This just make your code hard to maintain and inefficient. Have a look at this documentation as I think it should give you an idea of how you could use interfaces in your case: https://docs.oracle.com/javase/tutorial/java/IandI/interfaceAsType.html

Notice that all classes in Java inherits from the Object class, so you could have a container of Objects like this:

ArrayList objectList = new ArrayList();

And it should hold any of your instantiated objects. It becomes more tedious if you want to invoke functions defined in derived classes of these objects. To do this would require to do type casting. You might need to do this when using interfaces. There are some user cases that you can avoid this type casting but all boils down to your design. Maybe you should discuss a bit more about:

  1. Why you should interfaces
  2. Example code of what you are trying to implement. No need to provide full code, but better to provide a small sample showing the backbone and all the good stuff.

Finally, I checked an there are some previous posts similar to yours. For instance: https://discourse.processing.org/t/looping-different-class-instances/5843/10 It is a good idea to have a look at some of them. If something is not clear, you can cross-posted here and ask for further clarification.

Kf


#4

Thank you for your awnsers. It is still unclear how I can avoid adding dummy functions using an interface. An other ‘inconvenience’ was that, depending on what I had to do, I sometimes had to use enhanced for-loops and other times I had to use conventional for-loops.

Because all my classes share many functions. I decided to take a throw at inheritance and so far I am content. Ofcourse it was a bit tricky to acces the sub-class unique functions inside a for-loop using the array list, but I got the job done.

Every sub-class has a unique Draw function and I call them using:

// declarations
RailItem anyClass;                                            // anyClass is used inside loops as local variable even though it is actually a global one

ArrayList <RailItem> railItems = new ArrayList()

// in void draw()

for (int i = 0; i < railItems.size(); i++) {  
    anyClass = railItems.get(i);
    if(anyClass instanceof Switch) {  Switch sw = (Switch) anyClass; sw.Draw();}
    if(anyClass instanceof Detection) {Detection det = (Detection) anyClass; det.Draw();}
    if(anyClass instanceof Line) { Line ln = (Line) anyClass; ln.Draw();}
    if(anyClass instanceof Curve) { Curve cv = (Curve) anyClass; cv.Draw();}
    if(anyClass instanceof Memory) { Memory mem = (Memory) anyClass; mem.Draw();}
  }

The sub classes now have very little code as I don’t have to ctrl C ctrl V every function.
I can add as many objects as I want.

void mousePressed()
{
  if(mouseX > (width-2*gridSize)) {
    locked = true;
    
    switch(row) { 
      case 0: railItems.add( new Switch((width-2*gridSize)/gridSize,0,2,left,gridSize) ); break;
      case 1: railItems.add( new Switch((width-2*gridSize)/gridSize,0,2,right,gridSize) ); break;
      case 2: railItems.add( new Line((width-2*gridSize)/gridSize,2, 2, gridSize) ); break;
      case 3: railItems.add( new Curve((width-2*gridSize)/gridSize, 3, 2, gridSize) ); break;
      case 4: railItems.add( new Detection((width-2*gridSize)/gridSize, 4, 2, gridSize) ); break;
      case 5: railItems.add( new Memory((width-gridSize-edgeOffset)/gridSize,5, 0, gridSize) );break;
      //case 6: objectArray.add( new Button((width-gridSize-edgeOffset)/gridSize,6,gridSize) ); break;
    }
    index = railItems.size() - 1;
  }

Anyways thank you for your anwsers it was most educative.

bask185


#5

It sounds like maybe Abstract classes could work better for you from the sound of your comment. Notice in the link, there is a a guideline of when to use Abstract and when to use interfaces. This is a very light guide and it will really depend in your use case at the end.

My suggestion is that you explore previous post with this type of discussions. You don’t have to limit to the forum but to any content where OOP is discussed. I have no doubt your actual case has been discussed before as that is a common question. I encourage you to explore a bit further and take this opportunity to research OOP and apply it to your case.

You can also share another minimum code showing the nature and relation of these common functions between your classes.

Kf