3

I am currently working on a school project. In this project, we are supposed to first model the world seen from a doctor's perspective, including his patients, different pharmaceutical drugs (with interfaces such as liniment, pills and injections), prescriptions for drugs and containers for prescriptions and persons.

This is what the first part of the assignment says: A pharmaceutical drug has a name, unique number and a price. A pharmaceutical drug is of type A (narcotic with an associated int representing how narcotic/potent the drug is), type B (strongly addictive with an associated int representing how addictive the drug is) or type C ("normal" without the associative int that the two other types have).

Types A, B and C are supposed to be implemented as interfaces. My problem is the way that I'm supposed to structure the classes; I strongly disagree that this is the best way to organize the classes, but upon researching different approaches, I find myself puzzled as to what is the best implementation.

I want to do something like this. Pharmaceutical drug could be an abstract class with 3 concrete subclasses:

                               PharmaceuticalDrug

                            /           |           \

                       Liniment        Pill       Injection

My problem is how do I implement type A, type B and type C because of the instance variables associated with those types. Types A and B require an extra instance variable to represent their "potency", whereas C does not. I could simply include the instance variable and set type C's instance variable to a non-functional value (like -1) to indicate that that value is not to be used, but this approach does not seem like a pretty solution to me, as I am to write prescriptions with all info to files later on and would like an easy way to loop through and do this without unnecessary tests and special cases for type C.

I've tried to think out several ways to solve this. The instructors have stated that we could use Type A, B and C as interfaces and implement them accordingly, but to my knowledge I cannot implement an interface depending on whether it's this type or implement the another one if it's the other type. I read into dynamic proxying, but it didn't seem like the exact same thing. Maybe I am wrong. If so, I apologize for my ignorance.

I would, in that case, like to do something like this: (NOTE: I know this isn't working/real code and that implements should be after the class's name and inheritance from PharmaceuticalDrug, but it's just in order to illustrate what it is I'd like to do).

    public class Liniment extends PharmaceuticalDrug {
        ...

        public Liniment( String type ) {
            if ( type.equals( "A" ) ) {
                // make this class implement type A
            } else if ( type.equals( "B" ) {
                // make this class implement type B
            } else if ( type.equals( "C" ) { // type C
                // make this class implement type C **WITHOUT INSTANCE VARIABLE!**
            } else {
                System.out.println( "Error!" );
            }
        }

        ...
    }

Another way I thought could work, is to make Types A, B and C enums. However, I still don't know how I should tackle the unwanted instance variable I'd have for type C. I only want the instance variables associated with types A and B, as type C should have no extra features/instance variables.

The last way I thought I could do this: Make subclasses of Liniment, Pill and Injection, I.E. LinimentTypeA, LinimentTypeB, LinimentTypeC, PillTypeA, ..., InjectionTypeC. While this works, this looks ugly, makes a lot of repetitive code and makes me feel like there is a much simpler solution to my problem.

I want to be able to implement type A, B or C depending on which drug it is AND add/have an extra instance variable if the type is A or B, but NOT if the drug is of type C

Any ideas as to how I could best solve this problem?

3 Answers3

1

I could simply include the instance variable and set type C's instance variable to a non-functional value (like -1)

That is indeed a bad way. Just do it the "logical" way. Inheritance is the "is a" relation. Type A, B and C are Drugs. So indeed they are subclasses of Drug. A and B have indeed an int property extra. It's even best to name the properties different: int potency for type A and int addictivity for type B.

The instructors have stated that we could use Type A, B and C as interfaces and implement them accordingly

That means that Drug is the super interface. TypeA, TypeB and TypeC are also interfaces that extends Drug. Implement them accordingly means that you have to create at least one concrete class that implements each Type.

The interfaces should contain the getters for the necessary properties.

One of the advantages of using interfaces is that you can inherit from more than one interface in Java. So you can implement for example concrete class: public class Marjuana implements TypeA, TypeB

K.C.
  • 2,084
  • 2
  • 25
  • 38
1

For your drug type problems, you could do something like this:

  • a general interface for drugs that holds all common methods
  • an extension of the above interface for the A and B types that have that potency thing, with some getPotency()-like methods
  • then you can create the A and B types as extensions of the above, and C as an extension of the general interface
  • after that, your concrete drug implementations will be able to implement multiple drug types

Then, for your concrete LinimentTypeA and the like, you could try implementing a Factory pattern, which spits out instances of different extensions of your Liniment class (for example), depending on your type. An example:

class DrugFactory {
  public Liniment getLinimentInstance(String type) {
    switch (type) {
    case "A": return new Liniment() { // your overrides and other stuff here } ;
    // etc
    default: return null;
  }

  public Pill getPillInstance(String type) {
    // similar
  }

  // other stuff you might want
}
webuster
  • 2,490
  • 18
  • 27
0

You might consider:

  1. Add a potency variable to the superclass for drug
  2. Define three interfaces (TypeA, TypeB, TypeC)
  3. Define interfaces for Liniment, Pill, Injection
  4. Then create subclasses of PharmaceuticalDrug like: TypeALiniment, TypeBLiniment, TypeCLimiment, etc.

where you use public class TypeALiniment extends PharmaceutialDrug implements TypeA, Liniment {xxx}

ErstwhileIII
  • 4,829
  • 2
  • 23
  • 37