Search code examples
javasubclasssuperclass

How to cast a different subclass to a superclass in a loop?


I am writing a markup parser in Java. I have created classes for each kind of token based on a superclass (generic?) I'm calling BaseToken. Inside each token is a Pattern object and a String for the content. I am writing a function that finds the nearest token in a string from a certain start point in the string. In order to find out what pattern will work best, I have created an array of BaseToken instances that will be looped over when testing.

BaseToken is defined as:

public class BaseToken{
    public Pattern pattern = null;
    private BaseToken[] children;
}

An example of a subclass of BaseToken looks like this:

public class H3 extends BaseToken{
    public Pattern pattern = Pattern.compile("\\=\\=\\=([^\\s*].*?)\\=\\=\\=");
}

My problem with this is that in order to access the Pattern specific to the subclass, I need to specifically cast that subclass to its instance inside the array. Since the token types will be different each loop, I can't just cast it with (subclass)instance.

I've tried to search for similar situations to mine but I don't actually know what to search for. If this is a duplicate of an existing problem, I'm sorry.


Solution

  • This is not the best way to make use of polymorphism. You should either turn BaseToken into an interface or into an abstract class, and create a method specific to manipulating the pattern. You should then have the subtypes implement that method, so that each class can manipulate its own pattern (which should be private to the class) in its own way without breaking the calling code (you should read on Liskov's substitution principle).

    A simple example:

    abstract class BaseToken {
       abstract Pattern getPattern();
    }
    
    class H3 extends BaseToken {
      private Pattern pattern = ...
    
      Pattern getPattern() {
        return pattern;
      }
    }
    
    class Whatever extends BaseToken {
      private Pattern aCompletelyDifferentPattern = ...
    
      Pattern getPattern() {
        return aCompletelyDifferentPattern;
      }
    }
    

    With this, you can now do something like:

    BaseToken token = new H3();
    Pattern currentPattern = token.getPattern();
    

    No matter what subclass you use, this will always return the corresponding pattern.