How to determine right Class to use, if not equal to used variable's Class?

The question might be confusing and i don’t know how to explain it better, but an example should show what i mean.

Lets say we have some objects with different classes <Banana, Apple, Bread, and so on>.
And now i want to get their respective classes supercathegory like <Fruit, WheatProduct, and so on>.
Usually i would just make the class be Fruit and have Banana extend it (or implement it, not too much experience using that). But if i can’t do that, how would i go about saving their respective target class. So lets say we have Banana already extend (or so). And lets say we could not just change extension order, like Plant>Fruit>Banana, but have to have Plant>Banana, and then we need to access Fruit, from within Banana.

That could be done by just writing (Fruit) before the variable that would need this, or inside the ( element brackets, don’t know what they are called exactly, but those that define the class used ie. for a container), but the first is not modular once executed, and the second is not what i’m looking for. Now, i want the Banana object know that it should know that it is a Fruit, and that it can access some of Fruits methods and variables. How would i do that?

I mean, one option is to have each class have an ObjectArray with all classes that the Banana or Bread could be in, and then just get them via index (or strings for hashMaps) but that would require every class to have a whole array of objects in it. The other method would be to add a switch statement with and just set to Fruit if the String input is “Fruit”, but thats also a bit ugh… And just having the whole code switch once for each cathegory, is way too inefficient.

So, this could have proably been abbreviated by just saying that i’m looking for a way to store a Class in a Variable. (And so that it is not an Object and not a (elemental thingy))

Sorry for the confusing example :sweat_smile:

To answer the question you asked, you can store a class in a variable:

class Banana{
  Class<Fruit> fruitClass = Fruit.class;
}

class Fruit{
  void grow(){
    println("grow");
  }
}

But this doesn’t give you the ability to access Fruit functions from the Banana class. You might be able to do this using reflection, but this is almost certainly a bad idea.

Instead, I’d try to go for a simpler approach. Could you use composition instead of inheritance? Something like this:

class Banana{
  Fruit myFruit = new Fruit();
  
  void grow(){
    println("Banana grow");
    myFruit.grow();
  }
}

class Fruit{
  void grow(){
    println("Fruit grow");
  }
}

If this doesn’t work, can you try to put together a simple example that demonstrates what you’re trying to do?

1 Like

I think the first example is pretty close to what i’m looking for, if it is possible to use it in a modular way. The second one not so much, since it would (as far as i see it) require a variable for each possible class.

Though, as i said, i’m not good at explaining it, and my example was also quite lacking, so i’ll try to make a code with composition (i think… i’m not really good with the terminology) to show where the problem lies, and then try to show what i mean by modulay for the first example.

Lets assume we have the cathegory classes : Raw, Cooking;
And the other cathegory : Fruit, WheatProduct, Vegetable, Meat;
And then the classes : Apple, CookedBanana, RawBacon, Bread, Potato;

Where Apple and CookedBanana extend Fruit;
RawBacon extends Meat;
Bread extends WheatProduct;
And Potato extends Vegetable;

And where Apple is part of Raw (this “part of” is what causes the problem);
CookedBanana is part of Cooked;
RawBacon is part of Raw;
Bread is part of Cooked;
Potato is part of Raw;

So the problem in the composition is as follows :

class Raw{
  void stuff() {
    println("is Raw");
  }
}

class Cooked{
  void stuff() {
    println("is Cooked");
  }
}

class Fruit {
  void "is Fruit";// i'll just abbreviate this, since it's just so repetetive
}

class Vegetable {
//its always just println("is" + this.class), so i'll just leave that out...
}

class WheatProduct {

}

class Meat {

}

class Apple extends Fruit{
Raw myRaw = new Raw(); //would be all, if i knew it beforehand, but since i don't know what it's gonna become after runtime i also need : 
Cooked myCooked = new Cooked(); //now i only got 2, so it's no problem, but if there where more, it would mean that each class would need another 100 variables to have it be able to change what class it should be part of (not extending, but the "part of" i mentioned earlier.
}

class CookedBanana extends Vegetable {
// same for this one... so each class will have to have another 100 variables if you don't have just 2, but 100 classes to be part of in it.
}

//and so on for the others...

So that was why with composition i can’t get what i want (i think…).
And what the store class in variable would allow (if it was modular, which i’d like to know) is to use it like this :

class CookedBanana extends Fruit{
  Class partOf;// the class part should be what is modular, could also look like :
  Something<Class> partOf2;

    CookedBanana (Class class) {
      partOf = class;
      partOf2 = class; //or 
      partOf2<class> = class; //or whatever would have a result like this has, if it worked...
    }
}

Edit: i also thought about having it like :

class CookedBanana<Element_Class> extends Fruit{

  Element_Class myClass = new Element_Class(); //or if thats not gonna work
  SomeClassThatCanBeUsedLikeThis myClass1;
  CookedBanana<Element_Class>() {
    myClass1 = Element_Class; // or so...
  }
}

Sounds like you might be looking for the command pattern?

Basically, you’d want to create a top-level interface like this:

interface FoodAction{
  void act();
}

Then you’d create implementations of that interface for each behavior you want to model:

class Raw implements FoodAction{
  void act(){
    println("is raw");
  }
}

class Cooked implements FoodAction{
  void act(){
    println("is cooked");
  }
}

Then you could use instances of FoodAction like this:

class Banana{
  ArrayList<FoodAction> actions = new ArrayList<>();
  
  Banana(ArrayList<FoodAction> actions){
    this.actions = actions;
  }

  void doAllActions(){
    for(FoodAction action : actions){
      action.act();
    }
  }
}

There are a bunch of different ways to organize this, but hopefully that shows the general approach.

1 Like

Thanks :blush: I think thats pretty much what i‘m looking for.
But to be sure, is it correct to use it like this ? :

Interface FoodAction {
  void showType();
}

class Raw implements FoodAction{
  void showType() {
    println(„is Raw“);
  }
}

class Fruit{
  void cathegory() {
      println(„is a Fruit“);
  }
}

class Apple extends Fruit {
  ArrayList<FoodAction> type;
  
  Apple(ArrayList<FoodAction> type_) {
    type = type_;
  }

  void data() {
    println(„is Apple“);//Print what this is. 
    cathegory();//Access Fruit method to Print what cathegory this is (Fruit, veg, meat and so on)
    type[0].showType(); //sry, Never really worked with ArrayList, so i just assume Thats how you get the 0th Element :sweat_smile:
//also, can you just use a Single Element, so not ArrayList? Something like Object<FoodAction> or similar. And can this be changed after Setting it once? I assume it can, But just to be 100% sure :sweat_smile:
  }
}

Yeah, overall that code looks fine to me. More importantly: does it work for what you need, and does it make sense to you? In the end that’s the only thing that really matters.

If you use an array, then you use the brackets:

String[] myArray = new String[2];
myArray[0] = "hello";
myArray[1] = "world";
println(myArray[0]);

If you’re using an ArrayList, then you can use the add() and get() functions:

ArrayList<String> myArrayList = new ArrayList<>();
myArrayList.add("hello");
myArrayList.add("world");
println(myArrayList.get(0));

Sure, you absolutely could do that.

Yep, you could do that as well. You could add something like a addType() or setType() function to your class.

Thanks, then that‘s exactly what i was looking for. Also, i actually wanted to write .get(0), But then if that was not how to get it… well Yeah :sweat_smile:
Also, i just realized that the Single object Would just be FoodAction action; instead of Object<FoodAction> action; right? :sweat_smile:

Yes, that’s exactly right.

ArrayList needs the <FoodAction> part because it’s telling the compiler what type of objects the ArrayList will hold. This is called generics. If you just have a single item, you don’t need it.

2 Likes

Given all of your classes so far had been about food only, how about having an interface Food as a common trait for all of your concrete classes? :bulb:

/**
 * Food OOP Inheritance (v1.01)
 * GoToLoop (2018/Nov/27)
 *
 * Discourse.Processing.org/t/
 * how-to-determine-right-class-to-use-
 * if-not-equal-to-used-variables-class/5940/9
 */

void setup() {
  println(new Omega3());
  println(new Banana());
  println(new Beef());
  println(new CookedBanana());
  exit();
}

// Food - Common trait for all subinterfaces & subclasses

interface Food {
  enum State { 
    UNKNOWN, RAW, COOKED, FRIED, BAKED, BOILED, GRILLED
  }

  State getState();
}

// Substance, Plant, Animal

interface Substance extends Food {
}

interface Plant extends Food {
}

interface Animal extends Food {
}

// Oil, Fruit, Meat

interface Oil extends Substance {
}

interface Fruit extends Plant {
}

interface Meat extends Animal {
}

// Omega3, Banana, Beef

class Omega3 implements Oil {
  @Override State getState() {
    return State.RAW;
  }

  @Override String toString() {
    return getState() + " " + getClass().getSimpleName();
  }
}

class Banana implements Fruit {
  @Override State getState() {
    return State.RAW;
  }

  @Override String toString() {
    return getState() + " " + getClass().getSimpleName();
  }
}

class Beef implements Meat {
  @Override State getState() {
    return State.GRILLED;
  }

  @Override String toString() {
    return getState() + " " + getClass().getSimpleName();
  }
}

// CookedBanana

class CookedBanana extends Banana {
  @Override State getState() {
    return State.COOKED;
  }
}
2 Likes

Thanks :blush: then that‘s what i‘ll need :blush:

Thanks, that‘s pretty close to what i Need, But there is a problem with ‚modularity‘ that i Would Need. Here‘s what the code Would Need to be Perfect :

class CookedBanana extends Banana {
  String whatState; // a String to change states at runtime (Or something different if that doesn‘t work

  void setState(String st) {// set the new state
    whatState = st; //what‘s the new state
  }

  @Override
  State getState() {
    return State.whatState; //return the state that was set before... might not work with String, or any other way. 
//But that is essentially what it Would Need if it was only about states.
//But i also Need to Access the respective class. 
//in this case the class Cooked
  }
}

So, if such a setState method does exist, that Would sure be an Alternative to what i‘m trying, But i‘d still Need to Access a specific class, and Even though i‘m not too familiar with enums (because they apparently Need an extra .java tab or so, and i Never really used them because of that) i‘m pretty sure they can‘t be used to call classes, or can they?

I’m not really sure what you’re asking. Are you looking for this?

String getState(){
  return whatState;
}

Can you explain what your real end goal is?

The code you Sent was what i needed, i just Replied to GoToLoop as for why with his code i could achieve the Same, But it‘s not what i was looking for, as i wanted to return the possibility to Access methods this way, and enums don‘t have methods (Though i‘m Starting to think i saw an enum example that had methods… Or maybe i‘m just getting old). Well, at least that‘s what i tried to express. And the code describes what the code Would Need to be able to do, to at least be usabile in the way i Need it.

Or short : the Problem was that i still needed to set the corresponding state in the class, which means i can‘t change it at runtime and that‘s Part of what i needed (Though mainly the Access to a class part).

In the end, my question is answered with your Interface implementation :wink: . Thanks again :blush: