Home > database >  Creating child class based on class content
Creating child class based on class content

Time:12-21

I have a class structure like this:

                        LineTemplate (abstract)
                        /                    \
                LineOut (abstract)        LineIn (final)
                /                \
LineOutTransfers (final)     LineOutSells (final)

Both LineOut and LineIn should read a line from a file, check its content against a database and run multiple queries.

LineOut, however, contains two slightly different variations, which depend on the contents of the line. Due to the fact that LineOutTransfers and LineOutSells perform different actions when their methods are called, I decided to inherit and treat them as subclasses.

I created a public static LineTemplate __init() method within LineTemplate to determine whether it is a LineOut or LineIn class and return the correct type based on external conditions, and I wanted to implement a similar method to determine the correct type of LineOut subclass.

Since the LineOut child depends on the line content, however, I'm stuck at this point. The class should read the line, then convert itself to the correct child and then perform the checks. But this is impossible as I cannot cast a parent class into a child, if it is not already of that type (polymorphism).

I also thought about reading all the line inside LineOut's __init() method, and then passing the variables as arguments to its child constructor, but since there are a bunch of variables to be read and since it is done differently inside LineIn, it seemed to me like a bad practice.

Any ideas? Thanks in advance.

CodePudding user response:

Can you add a convertWithContext(SomeClassRepresentingContext ctx) method to LineOut that will return a new LineOut that will be the correct subclass of LineOut?

Another approach would be to use a Factory method and supply it the line content and the context. Something like

LineOutFactory.instance().constructLineOut(String line, SomeClassRepresentingContext ctx);

In Java you cannot change the type of a class once it is created you can only build a new class based on the content of the existing class and possibly external context.

CodePudding user response:

Favor composition over inheritance, so instead of

abstract class LineOut {
  public void consume(Line l) {
    // ...
    subclassConsume(l);
    // ...
  }
  protected abstract void subclassConsume(Line l);
}
// and
class LineOutTransfers extends LineOut {
  protected abstract void subclassConsume(Line l) { ... }
}
class LineOutSells extends LineOut {
  protected abstract void subclassConsume(Line l) { ... }
}

you should do this

abstract class LineOut {
  private TransferLineHandler transferHandler;
  private SellsLineHandler sellsHandler;
  public void consume(Line l) {
    // ...
    if (isTransfer(l)) {
      transferHandler.consume(l);
    } else {
      sellsHandler.consume(l);
    }
    // ...
  }
  protected abstract void subclassConsume(Line l);
}
// with
class TransferLineHandler {
  public consume(l) { // stuff from LineOutTransfers }
}
class SellsLineHandler {
  public consume(l) { // stuff from LineOutSells }
}

This removes the "dynamic subclassing" issue altogether and makes the code more testable.

CodePudding user response:

Maybe a factory method would be useful for this scenario: https://refactoring.guru/design-patterns/factory-method

  • Related