Getting methods from a class that extends another class

62 views Asked by At

I have a class that extends another class. Depending on a user's input, if the input "A" then the class needs to be a subclassA, but if they input "B" it will be a subclassB. I have a variable that needs to be the main class. I can't access the subclass' methods because the variable I defined is from the main class. How can I get this to work?

Here is a broken down example. The myClass variable is used elswhere, so I need it to be available as the subclass everywhere.

public class Programm
{
   private static MainClass myClass;

   public static void main(String args[]) 
   {
      if (input == 'A') {
         myClass = new SubClassA();
         myClass.subClassAMethod(); // Can't do this becuse subClassAMethod isn't in MainClass
      } else {
         myClass = new SubClassB();
         myClass.subClassBMethod(); // Can't do this becuse subClassBMethod isn't in MainClass
      }
   }
}

I know i could put the subClassAMethod and subClassBMethod in the main class, but I don't want to be able to call those methods if it's not part of the subclass.

Is there anyway to make the myClass be declared to accept both SubClassA and SubClassB?

1

There are 1 answers

2
rzwitserloot On
 private static MainClass myClass;

This says: The variable myClass exists and is constrainted to either point at null, or point at an instance of a class such that this class is either MainClass, or some subtype thereof.

The way java is set up, is that java will therefore straight up refuse to compile any interaction with this variable unless it makes sense in all possible scenarios.

In other words, even if you can prove beyond all doubt that at some point in your code's flow, this variable must necessarily be pointing at an instance of MySubClassB, the compiler doesn't care about that.

Your code style is suspect. This isn't how you java.

Note that myClass as a variable name is just screaming 'I do not understand how any of this works'. It's highly misleading: A variable can only reference an instance, not a class.

As a sidenote, static is being abused in your snippet. Static is usually not necessary for most java projects and a relatively advanced concept. If you don't want to learn its specific implications, that's fine. But then you must not use it. main, for now, has to be static (soon it won't have to be, starting in JDK22+), so the solution is to get away from static immediately.

Here's an example of how you could do it. These snippets use better names for the types and variables in an attempt to make things more clear:

class Animal {}
class Cat extends Animal {
  void meow() {}
}
class Dog extends Animal {
  void howl() {}
}

class Main {
  public static void main(String[] args) {
    new Main().go();
  }

  void go() {
    example1('A');
  }

  private Animal animal;

  void example1(char input) {
    if (input == 'A') {
      var cat = new Cat();
      animal = cat;
      cat.meow();
    } else {
      var dog = new Dog();
      animal = dog;
      dog.howl();
    }
  }
}

If the code new SubClassA() and the code myObject.subClassAMethod() aren't close together then this won't work. You'll have to use instanceof to check if myClass (again, really bad name, that) is the right type. That would look like:

// as part of Main.java snippet as above:
public void tryToHowl() {
  if (animal instanceof Dog dog) dog.howl();
}

This checks if animal is pointing at an object that is an instance of Dog, or some subtype of the type Dog. If it is NOT, the if does nothing as you'd expect (animal is NOT an instanceof Dog, hence the if does not execute its content). If it IS, a new variable Dog dog is created pointing at it, typed Dog, so you can invoke dog-only methods on it.

Note that usually using instanceof means your code is badly set up. The whole point of having a variable Animal animal is that it can contain any animal - if your code actually kinda needs that to be a dog, then, it should be Dog dog. Or you should have a subclass of whatever this code is, one version that is specifically catering to Dogs with a field defined as Dog dog in it. And if it's a method that encodes specifics for many kinds of objects (a big list of if (animal instanceof Cat cat) doCatThing(); else if (animal instanceof Dog dog) doDogThing(); and so on), then that should really be an abstract method in class Animal, with each implementation of Animal providing an implementation: The file with class Dog would contain the dog-specific code, because that's the place where dog specific code is meant to go.

Either way, you don't need instanceof, hence, if you do use instanceof, that's, especially if beginning coders are doing it, 95%+ a code-style wise very bad way to do it. 'bad' in the sense of: Hard to understand, inflexible (future changes in code requirements, which all non-academic projects always go through, require more effort than you'd think), hard to integrate into existing libraries, generally un-java-like, i.e. - not the way most java coders on the planet would do it, hence needlessly complicating the learning and understanding curve of that code.