Reputation: 711
this might be something very obvious but i am really struggling with the problem, any help would be appreciated.
i am trying to make a program that has an Activity
class, which is a superclass for Run
Swim
Cycle
classes, and there is another class called member.
a member has an arraylist called diary which keeps records of the distances made by a member
private ArrayList<Activity>diary = new ArrayList<>();
activities are added like so:
public void addActivity(Activity a){
diary.add(a);
}
now i need to get the distances for each of the classes in to an array and display the correct distance covered in each type of activity, i tried doing this:
public double[] getTotalDistances(){
double distance[];
distance = new double[3];
for (Activity r: diary){
distance[0] += r.getDistance();
}
for(Activity c: diary ){
distance[1] += c.getDistance();
}
for(Activity s: diary ){
distance[2] += s.getDistance();
}
for(int i = 0; i < distance.length; i++){
System.out.println(distance[i]);
}
return distance;
}
but this returns the getDistance() method of only the superclass, if i do this:
for (Run r: diary){
distance[0] += r.getDistance();
}
then java complains that those are incompatible types :
incompatible types. required: run, found: activity.
if run is a subclass of activity then why would it complain about incompatibility? and how do i get it to work with the correct method (the getDistance method that is in the "run" class)
THanks!
Upvotes: 0
Views: 69
Reputation: 31206
You can't do inheritance like this. The runtime won't filter out all of the run
s from the things that aren't run
s in your diary
you should instead do something like the following with the instanceof
operator
for (Activity r: diary){
if(r instanceof Run){
distance[0] += r.getDistance();
}
}
Upvotes: 0
Reputation: 95598
You already typed your list diary
as ArrayList<Activity>
, which means it contains elements of type Activity
. Then you're asking Java to iterate by assuming that the list contains Run
items, which it doesn't. This is because the list can contain any subclass of Activity
and it doesn't make sense to assume one. So you really can't do more than:
for(Activity activity : diary) {
...
}
Now in the following three loops:
for (Activity r: diary){
distance[0] += r.getDistance();
}
for(Activity c: diary ){
distance[1] += c.getDistance();
}
for(Activity s: diary ){
distance[2] += s.getDistance();
}
You're doing the same calculation three times! All you've done is given different names to the Activity
instances (r
, c
, and s
) so there is no way you can figure out what kind of activity it is. You could do instanceof
checks like so:
for (Activity activity : diary){
if (activity instanceof Run) {
distance[0] += activity.getDistance();
} else if (activity instanceof Cycle) {
distance[1] += activity.getDistance();
} else if (activity instanceof Swim) {
distance[2] += activity.getDistance();
}
}
This would work, but isn't very elegant. Instead let the object tell you what type it is. Create an enum
called ActivityType
and have your abstract Activity
class have a method called getActivityType
:
public abstract class Activity {
...
...
public abstract ActivityType getActivityType();
}
Then each subclass would implement this method and return the proper type:
public class Run extends Activity {
...
...
@Override
public ActivityType getActivityType() {
return ActivityType.RUN;
}
}
and so on.
Then in your loop, you just need to do this:
for (Activity activity : diary){
if (activity.getActivityType() == ActivityType.RUN) {
distance[0] += activity.getDistance();
} else if (activity.getActivityType() == ActivityType.CYCLE) {
distance[1] += activity.getDistance();
} else if (activity.getActivityType() == ActivityType.SWIM) {
distance[2] += activity.getDistance();
}
}
Upvotes: 2