1

Scenario:

[Updated] A class Creditor can be of an Org or Personnel type. A creditor can be of type A, type B or type C. Here type A is Org, and type B is Personnel. I want to know how I might implement this in the best Java-ish way.

  1. Have both classes implement an interface and have this third class be an instance of the interface these classes implement. (use Interface as a type)

OR

  1. Have a generic class, so that I can instantiate any class I want ? (Use generic class )

Which is more preferred or are they totally different thing ? What am I missing? Also explanations.

I have the following two classes Org and Personnel.

public class Org implements Entity{
  private String name;

  public String getName(){
    return this.name;
  }

  public void setName(String name){
    this.name = name;
  }

  public Org(String name){
    this.setName(name);
  }
}

public class Personnel implements Entity{
  private String name;

  private String phoneNumber;

  public String getName(){
    return this.name;
  }

  public void setName(String name){
    this.name = name;
  }

  public void setPhoneNumber(){..}

  public Personnel(String name){
    this.setName(name);
  }
}

The interface Entity that both the above classes implement"

interface Entity{
  String getName();
}

Case 1 and Case 2 codes are below.

Case 1.

Here, third class named Creditor can be an Org or a Personnel, so I have added an Entity interface as type, to reference this class Creditor to either Org or Person objects.

public class Creditor{

  public Entity entity;  

  public Creditor(Entity entity){
     this.entity = entity;
  }

  public static void main(String[] args){
    Org o = new Org("Name");
    Creditor c = new Creditor(o);
    Personnel p = new Personnel("AJ");
    Creditor c1 = new Creditor(p);
  }
}

OR

Case 2.

Instead of using Interface, why don't I just use generic type box and instantiate as per wish what object I want, like for example Personnel or Org.

public class Creditor<T> {
  private T t;

  public Creditor(T t){
    this.t = t;
  }

  public static void main(String[] args){
    Org o = new Org("Name");
    Personnel p = new Personnel("AJ");
    Creditor<Org> c1 = new Creditor<>(o);
    Creditor<Personnel> c2 = new Creditor<>(p);
  }
}
5
  • I guess the code doubling in case 1 makes it clear, that this is not a good approach. What would happen if you create 2 additional classes which Creditor can use? Create more and more constructors? Use case 2 and change your class to public class Creditor<T extends Entity>.
    – Tom
    Commented May 17, 2015 at 11:42
  • Up-voted because down-voter left no comment on why he/she did so.
    – Ruraj
    Commented May 17, 2015 at 11:45
  • 1
    Unless you tell us what you're trying to do with Creditor, we can't grive you an answer. @Tom: There is only duplicated code if you don't write a Creditor(Entity) constructor.
    – fabian
    Commented May 17, 2015 at 11:45
  • @fabian Updated. Please see and let me know if additional detail required. Commented May 17, 2015 at 11:51
  • @fabian If this question is not well phrased, I will delete it and post a fresh one. Commented May 17, 2015 at 12:21

2 Answers 2

1

Actually there is no difference between a Creditor in solution 1 and a Creditor<T extends Entity> in solution 2, other than the fact that Creditor<T extends Entity> is parameterized.

So the advantages and inconvenients of solution 2 are those of parameterization :

  • Main advantage is it allows for safe casting
  • It adds some formalism, which can be an advantage, but also an inconvenient. For example you will have to parameter all declarations of Creditor variables, and will get annoying warnings if you can't do it, which gets quite ugly if it is the case most of the time.

If you don't know, I suggest you start with solution 2 and remove parameterization if you realize inconvenients outnumber advantages. Refactor will be easier from solution 2 to solution 1.

1

There is no true answer to you question. In each way there is pros and cons, depend on the usages of the new Crediator class. For example, one pro of using generic method is that if you return the inner object, like this:

Org o = c1.get();

No casting back to the real type needed. So, try to consider how you class is going to look like and by this to decide which more suitable to your needs.

1
  • Actually there is a cast hidden in that code. The compiler handles that code as Org o = (Org)(c1.get()); (type erasure) You'll notice if you cast a Creditor<Personnel> that contains a non-null value to Creditor<Org> before calling get. The real benefit is that the compiler does checks on those type parameters.
    – fabian
    Commented May 17, 2015 at 11:56

Start asking to get answers

Find the answer to your question by asking.

Ask question

Explore related questions

See similar questions with these tags.