Reputation: 39
I am trying to learn about Interface and Abstract class and its uses.
Lets say, I have an Interface IPlan
. Have three classes implementing it, schoolPlan, highSchoolPlan, collegePlan
. If I want to write a createPlan()
service method that will accept any of this three plan type objects, how do I do it?
In my service class, if I do something like,
public String createPlan(IPlan plan) {}
As the passed object will be instantiated as IPlan, and I will not be able to access the variables of the objects I want to create. So, Should I bring in Abstract class, like
public String createPlan(AbstractPlan plan) {}
Or is this model completely wrong?
Upvotes: 1
Views: 93
Reputation: 1490
In the interface, you can not implement your methods there, just define them. According to your example, let try to do as below:
interface IPlan {
String createPlan();
}
public abstract class APlan implements IPlan {
@Override
String createPlan() {
//do something in general for schoolplan, collegeplan, highschoolplan.
}
}
public class SchoolPlan extends APlan {
@Override
String createPlan() {
super();
//do something unique for school plan here.
}
}
Also you can not use polymorphic arrays if you use the interface approach - but only if you make your classes inherit.
Upvotes: 0
Reputation: 31689
If there are instance variables that will exist in every IPlan
, regardless of what kind of IPlan
it is, then it's appropriate to have an abstract
class that defines the variables. In fact, you might consider defining just the abstract class, and not the interface. If the only use of the interface will be to have an abstract class implementing it, with everything else being a subclass of the abstract class, the interface doesn't serve much purpose.
If the variables are different for the different kinds of IPlan
s, then createPlan
shouldn't try to access the variables. It's a common beginner mistake to write code like
public String createPlan(AbstractPlan plan) {
...
if (plan instanceof SchoolPlan) {
return doSomethingWith(((SchoolPlan)plan).schoolType, ...)
} else if (plan instanceof HighSchoolPlan) {
return doSomethingElseWith(((HighSchoolPlan)plan).schedule, ...)
...
}
This defeats the purpose of polymorphism. Instead, you would want to ask: what parts of createPlan
are common between all the classes, and what things are going to be different between different subclasses? The things that are different can be turned into methods that you'd define in the abstract
class (ideally, if your "service class" is in the same package, you'd make them protected
methods so that createPlan
can use them but they wouldn't be usable everywhere else). For example, if the string returned by createPlan
contains a title that includes the description of the plan, but the description depends on different variables unique to each plan type, you could define a getDescription()
abstract method that you'd implement in each class.
[I'm not saying that instanceof
is always bad; but the cases where it's really needed are relatively rare, and generally you should look for an alternative.]
P.S. Using I
to indicate an interface is a C# convention that Java programmers tend to turn up our noses at.
Upvotes: 2