-3

Problem

BaseType has a field String jsonData that represents a JSON string.
The structure of the JSON string differs according to a field String dataType.
SubTypeA, SubTypeB, SubTypeC all extends BaseType, each having additional methods that parses super.getJsonData() appropriately.
A pseudo code of the intended usage is as follows:

for (el : baseTypeList) {
    if (el.getDataType.equals("A")) {
        result.add(((SubTypeA)el).getAlphaValueFromJson()); // ClassCastException
    }
    if (el.getDataType.equals("B")) {
        result.add(((SubTypeB)el).getBetaValueFromJson()); // ClassCastException
    }
}

However, this code wouldn't work since it's trying to cast Parent into Child.
Another way I could think of for getting around this problem is making an instanceBy() method for each of the SubTypeA, SubTypeB like below:

public class SubTypeA extends BaseType {
    private BaseType baseType;
    public static SubTypeA instanceBy(BaseType baseType) {
        SubTypeA subTypeA = new SubTypeA();
        subTypeA.setBaseType(baseType);
        return subTypeA;
    }
}

but as you can see, there's no reason to use inheritence in this case at all, since we won't be accessing super. Instead, we'd be using it directly from the field like: this.baseType.baseTypeSharedMethod();, this.baseType.getJsonData();.
I'm not sure what kind of a design pattern I should be using for this peculiar use-case.

  • This code: result.add((SubTypeA)el.getAlphaValueFromJson()) doesn't look right. It should be result.add(((SubTypeA)el).getAlphaValueFromJson()). See the extra parentheses around the cast? – Robert Harvey Jun 17 at 2:26
  • @RobertHarvey thanks, I've edited accordingly. – Gyuhyeon Lee Jun 17 at 2:27
  • Oh, so it still doesn't work? – Robert Harvey Jun 17 at 2:27
  • As I said, it's intended to show a wrong code - it's using inheritance backwards - at least in Java, it's impossible to cast a Parent(Basetype) into a Child(Subtype). Only the other way is possible(Bunch of different subtypes cast into basetype) – Gyuhyeon Lee Jun 17 at 2:29
  • So you're trying to call a super method from a subtype? – Robert Harvey Jun 17 at 2:32
1

but as you can see, there's no reason to use inheritence in this case at all, since we won't be accessing super

You are right that there is no point in making SubTypeX inherit from BaseType, but this does not mean that you are on the wrong track altogether. Amongst others the GOF promoted using composition over inheritance (Favor Composition over Inheritance [FCoI], see here, here), which means, that its often justified to compose an object from other objects, rather than inherit the respective class from a base class.

The reasons for FCoI are that base classes and inherited classes are very tightly coupled, which will eventually lead to code that is less evolvable. Furthermore it's easier to understand what a class does when FCoI is applied.

Getting back to your issue: I'd drop the extends BaseType from SubTypeX altogether (for convenience I will keep the name anyway, even though it ain't a base type anymore) and introduce an interface

public interface JsonParser
{
    public string getJsonValue();
}

your former subtype will now implement this interface and take the "base" via its constructor (you could still use the static method to create the instance, which is convenient to name the way you create your instance, but if there is is no way for a SubTypeA to exist without an instance of BaseType, you could legitemately skip this). SubTypeA will look like this

public class SubTypeA implements JsonParser
{
    private BaseType instanceOfBaseType;

    public SubTypeA(BaseType baseType)
    {
        instanceOfBaseType = baseType;
    }

    public string getJsonValue()
    {
        // do whatever you have to do
    }
}

Your top level code does not need to know whether SubTypeA has to do something with BaseType. You can push this knowledge down the hierarchy (of instances, not of inheritance). It's even conceivable that an object that inherits from JsonParser does not use BaseType at all.

Furthermore, if you have to make a decision what instance to create, I'd argue to leave this decision to a factory.

Your Answer

By clicking “Post Your Answer”, you agree to our terms of service, privacy policy and cookie policy

Not the answer you're looking for? Browse other questions tagged or ask your own question.