views:

366

answers:

4

I have a question about technique and implementation, rather than an actual problem to solve. Recently I created an abstract class, let's called it A, which defines the common behaviors of its subclasses.

I use this to construct several subclasses B, C, and D, which are then passed to some other method outside of the superclass-subclass structure which takes in a type A (thus being able to handle all of B, C and D).

In Java, I use instanceof to retrieve the true type, however I end up having to do a lot of casting to the real type, and it looks like a mess. Does anyone have any suggestions as to how to make the code cleaner?

One method I tried was by reconstructing an instance of the subclass type from the parameters of the superclass, so that I would be handling the object with it's actual type, thus avoiding typecasting. Since each of these subclasses are singletons (yes, they maintain state), I feel okay doing so. Does this seem like a crummy thing to do?

Thanks to anyone who answers, it is greatly appreciated!

Edit: I added further clarification in italics. Thanks.

+2  A: 

Generics are made to handle this.

Consider the following example:

public class SuperClass<T extends SuperClass> {

     public abstract void someMethod(T param);

}


public class SubClassA extends SuperClass<SubClassA> {

    public void someMethod(SubClassA param) {}
}

EDIT: Given the comment, I would say then that that is a design smell. The whole other class would either need subclasses to relate (at which point the same technique can be applied) or there is some other design issue involved. It is strange to have a method on a class that takes a super class of a different class and then proceeds to care about the sub type.

If that is what you need you could simply accomplish this with method overloading. Consider:

  public void someMethod(SuperClass param) {
      if (param instanceof SubClassA) {
         someMethod((SubClassA) param);
      } else if (param instanceof SubClassB) {
         someMethod((SubClassB) param);
      }
  }

  public void someMethod(SubClassA param) {}

  public void someMethod(SubClassB param) {}

But that hasn't gotten you out of the if trap. It depends on how many there are and how unstable they are to see if a heavier solution is worthwhile here.

Yishai
The method in question belongs to a whole other class entirely. It is not a method that belongs to the superclass or any of its subclasses.
AlbertoPL
Method overloading is probably what I need to be doing.
AlbertoPL
+3  A: 

I'm not understanding why you are having them inherit from the base class if you need to be checking the type. Abstract Class/Interface A defines a series of functions that B, C and D should implement and then the function that takes an instance of A should only ever call those abstract functions. If you need to call a function that only B contains (and therefore is not overridden), then your function should take an instance of B and not A.

Or am I completely missing the point? I've had no caffeine this morning.

MattC
The point is that the two only share certain methods. There are a lot of other methods and variables that exist only within the subclasses that are not shared or in any way compatible. I could define them in the superclass but then the other classes would have to keep those variables as null, which seems bad.
AlbertoPL
This sounds bad though since you're writing a function that's saying "If it's type B, do/get this B-specific thing. If it's C, do/get this C-specific thing. I would be breaking those out into different functions that were B/C/D specific. It seems like it's a monolithic thing that could probably stand to be broken out into individual functions.
MattC
Yes that is definitely something I am considering. Thank you.
AlbertoPL
Good luck, I get the sense you're not getting the answers you're looking for. :(
MattC
Actually, a combination of your answer and Yishai's (which leads to creating multiple methods via method overloading) seems best. I was hoping people would contribute other alternatives or critique my solution, but alas you can't always get the results you're looking for.
AlbertoPL
@AlbertoPL, I don't think we know enough about your problem (why you have an unrelated class, what type of processing you are doing) to effectively offer alternatives. The design smells wrong, but I can't say what would be better without knowing more about what you are trying to accomplish.
Yishai
A: 

It sounds like you want the visitor pattern. Personally I am not a massive fan but it works as follows:

class A { abstract void visit(MyVisitor visitor); }

this has to be implemented in each subclass:

class B extends A { 
    public void visit(MyVisitor v) { v.visit(this); }
}

So the actual visitor uses overloading as follows:

interface MyVisitor {
   public void visit(B b);
   public void visit(C c);
}

Now you can implement your visitor and call visit against your instance of A. Then the correct callback method will be called:

A a = new B();
a.visit(this);

Assuming the this instance implements MyVisitor, this will result in a callback on the visit(B) method

oxbow_lakes
A: 

As Yishai said, it looks like a design smell. If you have instanceof-s, which modifies behavior of your method, you a going a wrong way. Consider moving this behavior into the inheritors of A class.

Besides that you could use generics to parametrize A class. Here is a code sample

abstract class A<T extends A>{
   abstract protected void someMethod(T value);
}

class B extends A<B>{
 protected void someMethod(B value) {
 }
}

class C extends A<C>{
 protected void someMethod(C value) {
 }
}
wax