2

I am trying to write a set of User Interfaces that operate similarly for multiple classes, which all extend an abstract class Category: HouseCategory extends Category, CarCategory extends Category

Most of the code works fine just by using polymorphism, but there is one section where I need to create a new instance of the extended category

Obj foo = new HouseCategory(a, b, c)

How can I make this work for all subclasses of Category? - they all have the same constructor arguments. I don't know much about generics, but is it possible for me to have the UI class defined as

public class UserInterface <T extends Category> extends JFrame {

or possibly

public class UserInterface  extends JFrame {
     public UserInterface(Class<T extends Category> clazz) {

and build from there? Help much appreciated.

EDIT: Also, is it possible to get a static field from the generic class? I'd rather not have to have a statement checking "if (clazz instanceof HouseCategory) name = HouseCategory.NAME" as there may be hundreds of classes.

3 Answers 3

1

Introduce a new factory to create the category objects or the user interfaces. The factory needs to be extended whenever you add a new category, but that shouldn't be a big problem:

public class CategoryFactory {
  public static enum Type {HOUSE, CAR}

  public static Category createCategory(Type type, Param a, Param 2, Param b) {
    if (type == null) return null;

    switch(Type) {
      case HOUSE: return new HouseCategory(a,b,c);
      case CAR: return new CarCategory(a,b,c);
    }
    return null; // or throw exception -> tells, that a new enum is not handled yet
  }
}

Then, if you protect the constructors in the category subclasses and keep those subclasses and the factory in one package, you can make it pretty difficult to bypass the factory.

Sign up to request clarification or add additional context in comments.

4 Comments

That's an odd way of going about things. Why not make the enums the factory?
@Tom - is an enum based factory easier to understand or is it just more beautiful? This time I decided to help with an easy solution for the given requirement.
@Andread_D The implementation code is easier and its easier to use. Plus the question has an edit about static fields, and I think we can see where that is going.
OP - @Andreas_D @Tom. I understand the class you posted Andreas_D and that seems like a very good solution for me. I don't understand what you mean Tom by 'make enums the factory', could you please elaborate?
1

Generics can't really help you with this due to type erasure. At runtime your code doesn't "know" the values of the type parameters.

One approach would be to use the factory pattern. Create a factory class for each Category and have these all implement a common factory interface (probably CategoryFactory). Then give factory objects to the UserInterface rather than Class objects.

Another approach would be to use reflection to invoke the constructor on the Class object. I'm not a fan of this approach as it throws compile time checking out the window, but it would involve using the getConstructor method on the Class.

Comments

0

Pass the class to the interface. Use reflection to invoke the constructor and access the NAME field. But it's better to employ instance methods that subclass can override:

/** subclass must have the default constructor */
abstract class Category
    abstract void init(a, b, c);
    abstract String name();

class HouseCategory extends Category
    void init(a, b, c){ ... }
    String name(){ return "House"; }

class UserInterface
    UserInterface(clazz)
         Category foo = (Category)clazz.newInstance();
         foo.init(a,b,c);
         String name = foo.name();

1 Comment

No. There is no need for reflection here. Don't do it!

Your Answer

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

Start asking to get answers

Find the answer to your question by asking.

Ask question

Explore related questions

See similar questions with these tags.