1

I often have superclasses that contain a more abstracted form of a class as a member variable than my subclasses need. I find my code littered ((ClassName)variableName).methodName(). Is the best way to solve this to create a protected/private method called something like getVariableNameAsClass()? It's not much shorter in letters, but an IDE can do that much faster than maneuvering around with the keys to add in parenthesis. Or is there a better solution?

The reason I need to cast is because all of the subclasses of Line use an Output class, so I put the getters and setters that relate to the Output class in the base class. The issue is that an AudioLine uses and AudioOutput, and needs to define additional methods that use the more specific features.

So, here's my entire class design: I have a Line class with two subclasses, VideoLine and AudioLine, which delegate some of their functionality to a internal Output class. Output class has a AudioOutput and VideoOutput subclass. I defined all the functionality for the Line class that relies only on methods from the Output class inside the Line class, in accordance with DRY. Line's AudioLine and VideoLine both deligate additional functionality to AudioOutput and VideoOutput. Since they both set up the Output protected variable in their constructors (and therefor KNOW what subclass it contains), it seemed to make sense to caste it.

8
  • I don't understand. What's keeping you from just storing the more concrete form in the superclass? Aug 6, 2013 at 21:11
  • If you could give some details about the abstract class and what it's missing that you need to constantly cast it to other types for, we could maybe give you better guidance on solving your model design issue. Auto-casting methods like you refer to are really not a best approach most times, occasionally they're acceptable when using generics. Aug 6, 2013 at 21:12
  • @KarlBielefeldt Because the more concrete form is not used in all the subclasses.
    – sinθ
    Aug 6, 2013 at 21:16
  • @JimmyHoffa I added more information.
    – sinθ
    Aug 6, 2013 at 21:16
  • 2
    Show a class diagram. You have a design flaw. Aug 6, 2013 at 22:10

1 Answer 1

1

Declaring a protected Output field on Line implies that any implementation of Output can be used with any implementation of Line. In your case this is not true, and the repeated casts are a good indicator that your class structure isn't as type-safe as it should be.

(Imagine if, due to a change or a bug, Line were to replace the VideoOutput required by VideoLine with an AudioOutput - you wouldn't know until it crashed)

Recommendation:

Move the output field to the sub-classes. Two options (I prefer the former, but consider both valid):

1) Make the Output-dependent methods abstract and provide utility methods to do the work

public abstract class Line{
    public abstract void doThing();
    protected final void doThing(Output output){
        ...
    }
}
public class VideoLine extends Line{
    private VideoOutput output;
    public void doThing(){
        super.doThing(output);
    }
}

2) Provide a getOutput() method for the super-class to use.

public abstract class Line{
    public abstract Output getOutput();
    public void doThing(){
        Output output = getOutput();
        ...
    }
}
public class VideoLine extends Line{
    private VideoOutput output;
    protected Output getOutput(){
        return output;
    }
}
2
  • But is there a reason why this is better than casting it?
    – sinθ
    Aug 7, 2013 at 17:35
  • Type safety. I've updated my answer.
    – ajlane
    Aug 8, 2013 at 1:33

Your Answer

By clicking “Post Your Answer”, you agree to our terms of service and acknowledge that you have read and understand our privacy policy and code of conduct.

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