How to throw exceptions using inherited classes? - java

For my assignment, I am trying to throw an exception so that my program does not allow objects "Wolf" to eat "Plants". I am however struggling to find a way to implement this. I have so far tried using an if statement to search for the condition of food (x) being equal to "Plants" but this does not seem to be working. Here is the code:
Animal class
abstract public class Animal
{
String name;
int age;
String noise;
abstract public void makeNoise();
public String getName() {
return name;
}
public void setName(String newName) {
name = newName;
}
abstract public Food eat(Food x) throws Exception;
}
Food class
public class Food {
//field that stores the name of the food
public String name;
//constructor that takes the name of the food as an argument
public Food(String name){
this.name = name;
}
public String getName() {
return name;
}
}
Carnivore class
public class Carnivore extends Animal
{//if statement that throws exception
public Food eat(Food x) throws Exception
{
if (x.equals(new Meat("Plants"))) {
throw new Exception("Carnivores only eat meat!");
} else {
return x;
}
}
public void makeNoise()
{
noise = null;
}
public String getNoise()
{
return noise;
}
}
Meat class
public class Meat extends Food
{
public Meat(String name) {
super(name);
}
public String getName() {
return super.getName();
}
}
Wolf class
public class Wolf extends Carnivore
{
Wolf()
{
name = "Alex";
age = 4;
}
public void makeNoise()
{
noise = "Woof!";
}
public String getNoise()
{
return noise;
}
public String getName()
{
return name;
}
public int getAge()
{
return age;
}
public String eat(String x)
{
return x;
}
}
Main
public class Main {
public static void main(String[] args)
{
Wolf wolfExample = new Wolf();
System.out.println("************Wolf\"************");
System.out.println("Name = " + wolfExample.getName());
System.out.println("Age = " + wolfExample.getAge());
wolfExample.makeNoise();
System.out.println("Noise = " + wolfExample.getNoise());
Meat meatExample = new Meat("Plants");
System.out.println("************Wolf eating habits************");
System.out.println("Wolves eat " + wolfExample.eat(meatExample.getName()));
}
}
Output
************Wolf"************
Name = Alex
Age = 4
Noise = Woof!
************Wolf eating habits************
Wolves eat Plants//this should throw exception message
Any help on how to fix this to get the desired output would be greatly appreciated, thanks.

This code is causing the problem:
if (x.equals(new Meat("Plants"))) {
throw new Exception("Carnivores only eat meat!");
} else {
return x;
}
You don't have a equals method defined in your classes, so it compares objects using == operator - checking if the references are the same.
This expression:
x == (new Meat("Plants"))
is always false - new operator creates new instance of Meat object so the reference is always different.
Do not use equals to check types, use instanceof operator instead.
So your code should look like this:
public Food eat(Food x) throws Exception
{
if (x instanceof Meat) {
return x;
} else {
throw new Exception("Carnivores only eat meat!");
}
}
In that case you will need to define Plant class that extends Food.
Alternatively you can define equals method in your Food class that compares name field.
How to override equals method in java

Related

Code isnt working properly, unless i extend class

Im practicing polymorphism and inheritance, and i made a class (Animals) that sets the name of the animal, then i made a subclass (Cat) that sets the sound it makes, favourite toy.. all that. i tried testing it in a seperate class (Test) to print out "Cat likes to Moew, its favourite toy is Yarn" but its not working unless i extend Cat in the test class.
Heres my code.
Animals.java
public class Animals {
protected static String name;
public Animals() {
}
public Animals(String name) {
this.name = name;
}
public String setName(String newName) {
return this.name = newName;
}
public String getName() {
return name = name;
}
public static void animMove() {
System.out.println(name + " likes to walk");
}
}
Cat.java
public class Cat extends Animals {
public static String sound;
public static String favToy;
public String getSound(String sound) {
return this.sound = sound;
}
public String getToy(String favToy) {
return this.favToy = favToy;
}
public Cat() {
}
public Cat(String name, String sound, String favToy) {
super(name);
this.sound = sound;
this.favToy = favToy;
}
}
test.java
public class test{
public static void main(String[] args) {
Animals anim = new Animals();
Cat cat = new Cat("Cat", "moew", "Yarn ball");
System.out.println(anim.getName() + " Likes to " + cat.getSound(sound)
+ ", its favourite toy is a " + cat.getToy(favToy));
}
}
All works fine if i extend Cat to the test class, but when i dont, none of the variables like sound and favToy work. how would i do this without extending anything to the test class
Do not make the name variable static. This would mean that it belongs to the class and not an Animal object, meaning there will only ever be one Animal.name in the class. Your Cat.sound, Cat.favoriteToy variables are also static, which will mean all cats will have the same sound and same favorite toy (I guess this is acceptable, but then dont assign this in a constructor).
Setters don't need to have a return value (you are only changing some variable). For example:
public void setName(String newName) {
this.name = newName;
}
Getters do not need any parameters. You already know what to return, no need for a parameter. For example:
public String getSound() {
return this.sound;
}
Also, your Animals should be Animal, as this class represents a single animal.
If you create a Cat object, this will automatically be Animal as well (its inherited), so no need to create both, as you do in your main method
Cat myCat = new Cat("Purr","meow","ball"); //create cat
System.out.println(myCat.getName());
variables are static so all cats will have this name, sound and fav toy now...
Maybe you tried to do something like
1)
public class Animal {
protected String name;
public String animMove() {
return new String(this.name + " likes to walk");
}
}
2)
public class Cat extends Animal {
public String sound;
public String favToy;
public Cat(String name, String sound, String favToy) {
super(name);
this.sound = sound;
this.favToy = favToy;
}
public String getName() {
return super.name;
}
public String getSound() {
return this.sound;
}
public String getToy() {
return this.favToy;
}
}
3)
public class test{
public static void main(String[] args) {
Animal anim = new Cat("Cat", "moew", "Yarn ball");
System.out.println(anim.getName() + " Likes to " + anim.getSound(sound) + ", its favourite toy is a " + anim.getToy(favToy) + " " + anim.animMove());
}
}

Why am I not catching this exception properly?

I'm trying to catch an Exception that should show an error message but doesn't seem to be doing so. I have made another block of code that is exactly the same apart from the changes of some variable names and that catches an exception but this one doesn't seem to be doing so. The purpose of the exception is that the program should look for a Plant object and if it is not found it should throw an exception to show that herbivores only eat plants. Here is the relevant pieces of code:
Main method
import java.util.logging.Level;
import java.util.logging.Logger;
public class Main {
public Main() {
super();
}
Rabbit rabbitExample = new Rabbit();
public static void main(String[] args) {
Rabbit rabbitExample = new Rabbit();
System.out.println("************EXCEPTION 2************");
try {
Food pork = new Food("Prok");
System.out.println("************Herbivore caught Exception example************");
System.out.println("Exception caught");
rabbitExample.eat(pork);
//wolfExample.eat(vegFood);
} catch (Exception e) {
// TODO: Add catch code
e.printStackTrace();
}
try {
System.out.println("************Herbivore non-caught Exception example************");
Food vegiFood = new Plant("Vegetables"); // you create a Meat object and store it in a Food variable (so to speak)
System.out.println("Herbivores eat " + rabbitExample.eat(vegiFood)); // must be surrounded by a try-catch block
}
catch (Exception ex) {
// TODO: Add catch code
Logger.getLogger(Main.class.getName()).log(Level.SEVERE, null, ex);;
}
}
}
Animal class
abstract public class Animal
{
String name;
int age;
String noise;
abstract public void makeNoise();
public String getName() {
return name;
}
public void setName(String newName) {
name = newName;
}
abstract public Food eat(Food x) throws Exception;
}
Rabbit class
public class Rabbit extends Herbivore
{
Rabbit()
{
name = "Haryy";
age = 2;
}
public void makeNoise()
{
noise = "Squeek!";
}
public String getNoise()
{
return noise;
}
public String getName()
{
return name;
}
public int getAge()
{
return age;
}
public String eat(String Food)
{
return Food;
}
public Food eat(Food x) throws Exception
{
if (x.equals(new Plant("Meat"))) {
throw new Exception("Herbivores only eat plants!");
} else {
return x;
}
}
}
Herbivore class
public class Herbivore extends Animal
{
public Food eat(Food x) throws Exception
{
if (x.equals(new Plant("Meat"))) {
throw new Exception("Herbivores only eat plants!");
} else {
return x;
}
}
public void makeNoise()
{
noise = "Woof!";
}
public String getNoise()
{
return noise;
}
}
Food class
public class Food {
//field that stores the name of the food
public String name;
//constructor that takes the name of the food as an argument
public Food(String name){
this.name = name;
}
public String getName() {
return name;
}
#Override
public String toString() {
return name;
}
}
I apologist about the amount of code displayed but I wanted to show all relevant code required in order to run the program. The output is as displayed:
************EXCEPTION 2************
************Herbivore caught Exception example************
Exception caught
************Herbivore non-caught Exception example************
Herbivores eat Vegetables
Whereas the output should be:
************EXCEPTION 2************
************Herbivore caught Exception example************
Exception caught
java.lang.Exception: Herbivores only eat plants!
************Herbivore non-caught Exception example************
Herbivores eat Vegetables
Any help is appreciated, thanks.
Hetre is your problem:
public Food eat(Food x) throws Exception
{
if (x.equals(new Plant("Meat"))) {
throw new Exception("Herbivores only eat plants!");
} else {
return x;
}
}
Your Food subclass does not overwrite equals() (and hashcode()). The default implementation in class Object merrily does a == compare which is always false for different objects even if they are logically the same.
But resist the temptation to implement equals() (and hashcode()) in class Food. only concrete classes (classes you create objects from) can really tell if some other object is equal.
This if (x.equals(new Plant("Meat"))) will always yield false (unless the x parameter is passed as null) , therefore your exception will never be triggered because new Plant create a new reference in memory and it can't be equal to an an already existing reference

How to pass an argument that requires a parameter of type Food?

I am writing a program that is based on the demonstration of inheritance. I am trying to write an exception so that the only parameter that can be passed into the Meat class which is linked to the class Wolf. In essence, I am trying to allow the only parameter that can be passed into the eating method to be a Food variable called Meat. Here is the code:
Animal
abstract public class Animal
{
String name;
int age;
String noise;
abstract public void makeNoise();
public String getName() {
return name;
}
public void setName(String newName) {
name = newName;
}
abstract public Food eat(Food x) throws Exception;
}
Food
public class Food {
//field that stores the name of the food
public Food name;
//constructor that takes the name of the food as an argument
public Food(Food name){
this.name = name;
}
public Food getName() {
return name;
}
}
Meat
public class Meat extends Food
{
public Meat(Food name)
{
super(name);
}
public Food getName()
{
return super.getName();
}
}
Carnivore
public class Wolf extends Carnivore
{
Wolf()
{
name = "Alex";
age = 4;
}
public void makeNoise()
{
noise = "Woof!";
}
public String getNoise()
{
return noise;
}
public String getName()
{
return name;
}
public int getAge()
{
return age;
}
public Food eat(Food x) throws Exception
{
if (x instanceof Meat) {
return x;
} else {
throw new Exception("Carnivores only eat meat!");
}
}
}
Wolf
public class Wolf extends Carnivore
{
Wolf()
{
name = "Alex";
age = 4;
}
public void makeNoise()
{
noise = "Woof!";
}
public String getNoise()
{
return noise;
}
public String getName()
{
return name;
}
public int getAge()
{
return age;
}
public Food eat(Food x) throws Exception
{
if (x instanceof Meat) {
return x;
} else {
throw new Exception("Carnivores only eat meat!");
}
}
}
Main
public class Main {
public static void main(String[] args)
{
Wolf wolfExample = new Wolf();
System.out.println("************Wolf\"************");
System.out.println("Name = " + wolfExample.getName());
System.out.println("Age = " + wolfExample.getAge());
wolfExample.makeNoise();
System.out.println("Noise = " + wolfExample.getNoise());
Meat meatExample = new Meat(//Food argument goes here?);
System.out.println("************Wolf eating habits************");
System.out.println("Wolves eat " + wolfExample.eat(meatExample.getName()));
}
}
The problem I'm having is that I cannot pass in anything as a food argument within the new Meat object that I create within my main method. And I mm getting the error of an unsupported exception when I try to call System.out.println("Wolves eat " + wolfExample.eat(meatExample.getName()));which I think may be because a Food variable has not been passed in. The desired outcome is that a Food variable such as Plants is passed in which throws an exception message. Any help on how to resolve this is appreciated, thanks.
You will have to modify your Animal and Food classes first and then with few other changes in your Main class, you may be able to achieve what you are trying to. Here are few suggested changes:
public class Food {
//field that stores the name of the food
public String name;
//constructor that takes the name of the food as an argument
public Food(String name){
this.name = name;
}
public String getName() {
return name;
}
}
public class Meat extends Food
{
public Meat(String name) {
super(name);
}
public String getName() {
return super.getName();
}
}
public class Main {
public Main() {
super();
}
public static void main(String[] args) {
Wolf wolfExample = new Wolf();
System.out.println("************Wolf\"************");
System.out.println("Name = " + wolfExample.getName());
System.out.println("Age = " + wolfExample.getAge());
wolfExample.makeNoise();
System.out.println("Noise = " + wolfExample.getNoise());
try {
Meat meatExample = new Meat("Steak");
//Food vegFood = new Food("Spinach");
System.out.println("************Wolf eating habits************");
wolfExample.eat(meatExample);
//wolfExample.eat(vegFood);
} catch (Exception e) {
// TODO: Add catch code
e.printStackTrace();
}
}
}
So, If you call wolfExample.eat(vegFood); your code will throw exception.
First of all, your Carnivore class and Wolf class is same.
You have not passed name for your 'meatExample'
And try instantiating Meat object and assign it in Food class
Food meatExample = new Meat("Beef");
This way you are calling getName() method of Food class rather than from Meat class.
Basically, your Food and Meat class design is incorrect, which needs to be fixed as shown below i.e., Meat class should take the argument of food name property.
Food class:
public abstract class Food {
//field that stores the name of the food
protected String name;
public String getName() {
return this.name;
}
}
Meat class:
public class Meat extends Food {
public Meat(String name) {
super.name = name;
}
//other methods or add other specific meat fields
}
main() method:
public static void main(String[] args) {
//Create the Meat Object by sending the name in constructor
Meat meatExample = new Meat("Chicken");
//other code
}

Why do we use Strategy Pattern?

I just learned what the Strategy pattern really is from the Internet. But I wondered how it can improve my code. For example, i have the following codes found in the Internet like this. This is the Superclass named Animal:
abstract public class Animal {
private String name;
private int weight;
private String sound;
public void setName(String name){
this.name = name;
}
public String getName(){
return name;
}
public void setWeight(int weight){
if(weight > 0){
this.weight = weight;
}else {
System.out.println("Weight must be bigger than 0");
}
}
public int getWeight(){
return weight;
}
public void setSound(String sound){
this.sound = sound;
}
public String getSound(){
return sound;
}
public void specialMethod(){
System.out.println("Ok");
}
}
This is the subclass named Dog:
public class Dog extends Animal {
public void digHole(){
System.out.println("Dig a hole");
}
public Dog(){
super();
setSound("bark");
}
public void testSuper(Animal obj){
System.out.println(obj.getName());
}
}
In the tutorial, it said that if we want to add flying ability so that I can check whether dog can fly or not. Adding the code directly like this one is bad as shown in the code below.
The Superclass Animal with an added flying ability method
abstract public class Animal {
private String name;
private int weight;
private String sound;
// Add fly method to the superclass which is a bad idea
public String fly(){
return " I am flying ";
}
public void setName(String name){
this.name = name;
}
public String getName(){
return name;
}
public void setWeight(int weight){
if(weight > 0){
this.weight = weight;
}else {
System.out.println("Weight must be bigger than 0");
}
}
public int getWeight(){
return weight;
}
public void setSound(String sound){
this.sound = sound;
}
public String getSound(){
return sound;
}
public void specialMethod(){
System.out.println("Ok");
}
}
Using the Strategy pattern, we can create interface named Flys with the method fly, allowing any subclass to implement the method, thus as shown in the tutorial, I created Interface named Flys with 2 subclasses implementing the interface:
public interface Flys {
String fly();
}
class ItFlys implements Flys{
public String fly(){
return "Flying high";
}
}
class CantFly implements Flys{
public String fly(){
return "I can't fly";
}
}
Once I made the interface, I can refactor the class Animal,
abstract public class Animal {
private String name;
private int weight;
private String sound;
Flys flyingType; // Add an object of the interface to the superclass
public String tryToFly(){ // add a new method tryToFly
return flyingType.fly();
}
// Adding another method named setFlyingAbility
public void setFlyingAbility(Flys newFlyType){
flyingType = newFlyType;
}
public void setName(String name){
this.name = name;
}
public String getName(){
return name;
}
public void setWeight(int weight){
if(weight > 0){
this.weight = weight;
}else {
System.out.println("Weight must be bigger than 0");
}
}
public int getWeight(){
return weight;
}
public void setSound(String sound){
this.sound = sound;
}
public String getSound(){
return sound;
}
public void specialMethod(){
System.out.println("Ok");
}
}
Now, in my Dog subclass, I simply add another code
public class Dog extends Animal {
public Dog(){
super();
setSound("bark");
flyingType = new CantFly(); // I set flyingType object
}
public void digHole(){
System.out.println("Dig a hole");
}
public void testSuper(Animal obj){
System.out.println(obj.getName());
}
}
The final class is where I can execute all codes, checking whether my Dog class can fly or not.
public class AnimalPlay {
public static void main(String args[]){
Animal sparky = new Dog();
Animal tweety = new Bird();
System.out.println("Dog " + sparky.tryToFly()); // the result is I can't fly
System.out.println("Bird " + tweety.tryToFly()); // the result is I am flying
sparky.setFlyingAbility(new ItFlys());
System.out.println("Dog " + sparky.tryToFly()); // the result is I am flying
}
}
My question is, what about If I still add the fly() method the traditional way, it gives the same result, doesn't it?
Adding the fly() method to the superclass so I can override the fly() method in my Dog class, but this is not a good idea.
abstract public class Animal {
private String name;
private int weight;
private String sound;
// Add fly method to the superclass which is a bad idea
public String fly(){
return " I am flying ";
}
public void setName(String name){
this.name = name;
}
public String getName(){
return name;
}
public void setWeight(int weight){
if(weight > 0){
this.weight = weight;
}else {
System.out.println("Weight must be bigger than 0");
}
}
public int getWeight(){
return weight;
}
public void setSound(String sound){
this.sound = sound;
}
public String getSound(){
return sound;
}
public void specialMethod(){
System.out.println("Ok");
}
}
My question is, what about If I still add the fly() method the traditional way, it gives the same result, doesn't it?
The answer is 'NO'.
Strategy pattern allows you to move behavior into separate class which is good by SOLID principle 'S' - single responsibility. Image that you need to learn robot or human to 'bark' - you don't need to make them inherit animal base class. And you also don't need to implement barking in each class.
Having all properties in base class is also not good as it is against SOLID 'L' - Liskou substitution. What if monkey don't need to bark which is implemented in base animal class?
Strategy pattern allows you to design code accordingly to SOLID 'I' - Interface segregation - just make IAnimalAction interface make many implementations of barking and assign IAnimalAction property to desired animal classes (as property or as one more interface to implement)
Strategy also helps with SOLID 'D' - you can inject desired animal strategy (barking, flying) without having each animal even know about it
We can continue and find other bonuses. But you can see a picture
Good luck!
I am not sure which came first, but the Strategy pattern like any other behavioral pattern is a specific instance of the open close principle. In general you want to change the behavior of an object without having to change it's code. This has a profound consequences in terms of extendability, maintainability and coherence.

Why do I get this weird output?

I have three classes
public abstract class Champion
{
private String name;
public Champion(String ChName)
{
name = ChName;
}
public void setName(String ChName)
{
name = ChName;
}
public String getName()
{
return name;
}
}
second:
public class Mage extends Champion {
public Mage(String ChName)
{
super(ChName);
}
public String toString()
{
return String.format("%s",super.toString());
}
}
and my main:
public class JavaApplication2 {
public static void main(String[] args) {
Mage mage = new Mage("ori");
System.out.println("champion is "+mage);
}
}
The output should be "champion is ori"
but I get:
"champion is javaapplication2.Mage#1fee6fc"
What am I doing wrong?
You need to override toString() in Champion as the call to super.toString() in Mage.toString() will be calling Object.toString().
By calling super.toString() you call the Object toString() method, giving you the result you see.
You need to implement the Champion toString() method.

Categories

Resources