Reputation: 4702
I've built a kennel system that checks dogs into the system using .txt files, allows you to perform a variety of actions such as search, remove, print all etc.
I'm currently using inheritance to add functionality for cats as they share a lot of the same variables (name, favourite food etc).
I'm using a boolean unique to dogs and cats which is "does the dog like bones" for dogs and "can cats share a run" for cats.
I've ran into a problem using inheritance because the two booleans aren't the same (obviously) and use different variables/identifiers in the code (not sure of the correct terminology here, please let me know if possible) and it's throwing errors.
Here's what I have so far
import java.util.ArrayList;
public class Pet {
protected ArrayList<Owner> originalOwners;
//private boolean likesBones;
protected String petName;
protected String favFood;
protected int foodPerDay;
public Pet(String name, ArrayList<Owner> owners, String food, int mealsPerDay) {
petName = name;
this.favFood = food;
this.foodPerDay = mealsPerDay;
originalOwners = new ArrayList<Owner>();
for(Owner o: owners){
Owner copy = new Owner(o.getName(), o.getPhone());
originalOwners.add(copy);
}
}
public String getName() {
return petName;
}
public void setName(String newName) {
petName = newName;
}
/**
* Returns a copy of the original owners
* @return A copy of the original owners as an array
*/
public Owner[] getOriginalOwners(){
Owner[] result = new Owner[originalOwners.size()];
result = originalOwners.toArray(result);
return result;
}
/**
* How many times a day to feed the dog
* @param feeds The number of feeds per day
*/
public void setFeedsPerDay(int feeds){
foodPerDay = feeds;
}
/**
* The number of feeds per day the dog is fed
* @return The number of feeds per day
*/
public int getFeedsPerDay(){
return foodPerDay;
}
/**
* What's his favourite food?
* @param food The food he likes
*/
public void setFavouriteFood(String food){
favFood = food;
}
/**
* The food the dog likes to eat
* @return The food
*/
public String getFavouriteFood(){
return favFood;
}
/**
* Note that this only compares equality based on a
* dog's name.
* @param The other dog to compare against.
*/
@Override
public boolean equals(Object obj) { // Generated by Eclipse to be more robust
if (this == obj)
return true;
if (obj == null)
return false;
if (getClass() != obj.getClass())
return false;
Dog other = (Dog) obj;
if (petName == null) {
if (other.petName != null)
return false;
} else if (!petName.equals(other.petName))
return false;
return true;
}
/**
* A basic implementation to just return all the data in string form
*/
public String toString() {
return "Dog name:" + petName + "Original Owner:" + originalOwners + "Favfood:" + favFood
+ "FoodPerDay:" + foodPerDay;
}
}
The dog class:
import java.util.ArrayList;
public class Dog extends Pet {
public static boolean likesBones;
public Dog(String name, ArrayList<Owner> owners, String food, int mealsPerDay, boolean likeBones) {
super(name, owners, food, mealsPerDay);
Dog.likesBones = likeBones;
}
/**
* Does the dog like bones?
* @return true if he does
*/
public static boolean getLikesBones() {
return likesBones;
}
}
The cat class
import java.util.ArrayList;
public class Cat extends Pet {
public static boolean shareRun;
public Cat(String name, ArrayList<Owner> owners, String food, int mealsPerDay, boolean shareRun) {
super(name, owners, food, mealsPerDay);
Cat.shareRun = shareRun;
}
public boolean getShareRun(boolean doesShare) {
return shareRun;
}
}
I can't add in the boolean for both likeBones and shareRun to Pet() because they're from different classes, so if I'm trying to add a dog I get a null point exception (I believe) and vice versa for cats.
My question: how can I support both booleans for cats and dogs in the Pet() class without it throwing an exception?
Please let me know if this question makes sense, I've had some trouble explaining my issue before (new to programming). Thanks in advance guys.
Upvotes: 0
Views: 186
Reputation: 22553
Your Cat class is set up almost right with a private shareRun field and public getters and setters. But why does this class also have a public static shareRun field?
Your Dog class should follow the same pattern as Cat with regard to likesBones. Currently, you have it set up as a static property which is wrong.
If you are getting an error if you try to do something like
Pet fido = new Pet();
dodo.setLikesBones(true);
You will get a compiler error, since Pet doesn't declare that method.
You can declare those fields and methods on Pet, but then both cats and dogs have the option of liking bones and being able to share a run.
Use the base class to share common attributes and the child classes to make distinctions.
Does that make sense?
Upvotes: 0
Reputation: 3568
Hey I think you might want to force Dog and Cat to set the boolean declared in Pet. Maybe make an abstract method in Pet, then put it in the Pet constructor.
class abstract Pet {
...
public Pet() {
...
setRandomBoolean();
}
...
protected abstract void setRandomBoolean();
...
}
It is obvious, reading this code, that the property of liking bones (what dog doesn't?) and sharing runs are too abstract and unrelated.
Like BIU said, they should have completely seperate implementations.
Upvotes: 0
Reputation: 2430
Because likebones is specific to dogs it should only exist in the Dog class, not the parent Pet class. Likewise shareRun should exist only in the Cat class, not the parent Pet class.
Think about the structure logically. A parent class should contain information used by all its children - the point of it is to allow functionality to be shared. Functionality that is not shared does not belong in a place that is meant to help share functionality.
What you could do if you need functions that use that boolean for any child of Pet would be to define a generic boolean special
in the parent and implement functions that use it, and then somewhere else keep track for each type of Pet what its special
is - but not knowing your system I'm not sure it's the best for you.
Upvotes: 1