Trying to figure out Inheritance and polymorphism - java

I'm doing an exercise on Inheritance and polymorphism, I have 3 seperate clasees, my main class, a super Animal class, and a sub Cat class. I've made overloaded constructors, getters and setters, and toString() methods in both Animal and Cat classes. I think I have the inheritance part down. Now I need to make 2 Animal Object references, both an instance of Cat, example: one a type Siameese with a name Tobbie.
Could anyone give me an example of one of these object references? You can see I've attempted in my Main class there, but I'm not sure if that is correct.
Here are the three different classes I have currently.
public class Hw02 {
/**
* #param args the command line arguments
*/
public static void main(String[] args) {
Animal Siamese = new Cat("Tobbie");
}
}
Here's my Animal Class.
public class Animal {
private String name;
public Animal() {
this("na");
}
public Animal(String name) {
this.name = name;
}
/**
* #return the name
*/
public String getName() {
return name;
}
/**
* #param name the name to set
*/
public void setName(String name) {
this.name = name;
}
#Override
public String toString() {
return "Animal{"
+ "name="
+ name
+ '}';
}
}
And here is my Cat class.
public class Cat extends Animal {
private String type;
public Cat() {
}
public Cat(String type) {
this.type = type;
}
public Cat(String type, String name) {
this.type = type;
}
public String getType() {
return type;
}
public void setType(String type) {
this.type = type;
}
#Override
public String toString() {
return "Cat{"
+ "type="
+ type
+ '}';
}
}

// in main method
Animal tobbie = new Cat("siamese", "Tobbie")
Animal jackie = new Cat("tomcat", "Jackie")
// in Cat class
public Cat(String type, String name) {
super(name)
this.type = type;
}
A few comments:
It is not proper convention to have the name Siamese; variable names should be "camelCase" (start with a lower-case letter). Compiler will accept it is as you have written, but it is a bad practice.
Your Cat(String type, String name) constructor didn't invoke the proper superclass constructor, thus type was lost; same for the Cat(String type) constructor
I think I would make Animal abstract and its constructors protected. I think it is a bad practice to let clients directly instantiate Animals without specifying what kind of animals they are.
Edit:
Like this:
Animal animal = new Animal("What am I?")
However, I don't consider it a good practice to do this, probably what you want done is better achieved otherwise.
Edit:
Cat toString():
public String toString() {
return super.toString() + " Cat{type=" + type + "}";
}

With the code you have above, this is an example:
Animal animal0 = new Cat("Siamese", "Bob");
Animal animal1 = new Cat("Tomcat", "Frank");
Animal animal2 = new Cat("Tomcat", "George");
Animal animal3 = new Animal("Elephant");
System.out.print(animal0.toString());
System.out.print(animal1.toString());
System.out.print(animal2.toString());
System.out.print(animal3.toString());
Would produce the output:
Cat{type=Siamese}
Cat{type=Tomcat}
Cat{type=Tomcat}
Animal{name=Elephant}

Related

Error when extending from abstract parent class

Error
public Cat (String nm, int legs, String sd, String col)
For this constructor I got following compiler error:
constructor Animal in class Animal cannot be applied to given types;
required: String, int
found: no arguments
reason: actual and formal arguments lists differ in length
Code
The parent class is right below the child class.
public class Cat extends Animal {
private String sound;
private String colour;
public Cat (String nm, int legs, String sd, String col) {
nm = super.getName();
legs = super.getNumOfLegs();
sound = sd;
colour = col;
}
public abstract class Animal {
protected String name;
protected int numOfLegs;
public Animal() {
}
public Animal(String nm, int legs) {
name = nm;
numOfLegs = legs;
}
public String getName() {
return name;
}
public int getNumOfLegs() {
return numOfLegs;
}
public abstract String display();
}
}
Should the parent abstract class be placed in a separate file instead?
I've tried that initially but it returned way more errors than it did now, especially from the abstract method display().
What is causing the error?
There are a couple of things you should change.
First of all, it is the best way to put the super class into a separate file. If you want to keep in one file you need drag it out of the Cat class and remove the scope (not public or private). But this is not a good coding style for a super class.
The next thing is, with the name/nm and legs/numOfLegs. Either you call the super constructor and provide the two variables (see my example) or you use name = nm; and numOfLegs = legs;
You should also reconsider if the name and numOfLegs varialbes need to be protected or if is fine to provide the access only through the getter.
If the number of legs, the name, sound and color will not change you could also make them immutable (with the key word final, e.g. private final String sound). If not you can make them accessible with a setter.
Finally you need to implement the abstract method in the Cat class...
public class Cat extends Animal {
private String sound;
private String colour;
public Cat(String nm, int legs, String sd, String col) {
super(nm, legs);
sound = sd;
colour = col;
}
#Override
public String display() {
return null;
}
}
abstract class Animal {
protected String name;
protected int numOfLegs;
public Animal(String nm, int legs) {
name = nm;
numOfLegs = legs;
}
public String getName() {
return name;
}
public int getNumOfLegs() {
return numOfLegs;
}
public abstract String display();
}

Abstract class values are null after calling super

I have the following program:
public class Driver {
public static void main(String[] args) {
Animal dog = new Dog("larry");
dog.speak();
}
}
public abstract class Animal {
private String name;
public Animal(String name) {
this.name = name;
}
public abstract void speak();
}
public class Dog extends Animal {
private String name; // is this even needed?
public Dog(String name) {
super(name);
}
#Override
public void speak() {
System.out.println("I am " + name);
}
}
Running this program prints I am null, which is not what I want.
Why doesn't it just use the Animal variable defined name and print out larry?
What is the proper way to do this?
If I remove the name from the Dog class, is it possible to reference the Animal name variable while still keeping it private?
If so, how?
The name variable used in
System.out.println("I am " + name);
is the one defined in the Dog class. It is never set, hence null is printed.
There is no need to define name in both Animal and Dog. My suggestion would be to:
remove name from Dog
change the visibility of name in Animal to protected
If you want to keep the access to name as private, add a "getter" method for name to Animal, thus:
public class Animal {
private String name;
public String getName() { return name; }
}
public class Dog {
#Override
public void speak() {
System.out.println("I am " + getName());
}
}
You don't need the variable name in Dog; it is a separate variable from the one in Animal. The Animal constructor initializes the name in Animal correctly, but the speak method in Dog refers to the uninitialized name variable in Dog; the variable in Dog is the one that is in scope inside the Dog class code. Delete the name variable in Dog to avoid confusion.
But to keep name private in Animal and access it in a subclass, provide a getter method in Animal.
public String getName() { return name; } // or protected
Then you can call it in Dog:
System.out.println("I am " + getName());
Output:
I am larry

I need help creating constructors and returning boolean and strings

I need help fixing my code with the basic concepts listed above. To save from clutter, I took a screen shot of the directions here: https://imgur.com/SdiotUi
However, when I run my code it isn't working. I know there are a lot of errors but I'm having trouble fixing them even though I've spent the past few hours googling the correct way to do this.
When I create the first constructors I am not sure if I am assigning the name and legs correctly, I am having trouble returning "true", I get an error calling the parent class taking one argument, and I don't think I am overriding the abstract class correctly.
My code:
public class Animal1 {
private String animalName;
public int numberOfLegs;
public Animal1(String name){
name = animalName;
name = "John";
}
public Animal1(String name, int legs){
name = animalName;
legs = numberOfLegs;
name = "Jack";
legs = 4;
}
public String getName(){
return animalName;
}
public int getLegs(){
return numberOfLegs;
}
public void isAMammal(){
return true;
}
public void isCarnivorous(){
return true;
}
public abstract class getHello{
}
}
public class Cat1 extends Animal1{
public Cat1(String name){
Animal1.name;
}
public abstract class getHello{
return "Meow";
}
}
public class Dog1 extends Animal1{
public Dog1(String name){
Animal1.name;
}
public abstract class getHello{
return "Woof";
}
}
public abstract class Animal1 { // If you want to have an abstract method, declare the class as abstract
private final String animalName;
private final int numberOfLegs; // better of using private and make it final since it's not going to change.
public Animal1(final String name, final int legs){ //better making the input parameters final since they are not supposed to be changed
//name = animalName;
//legs = numberOfLegs;//it assigned the field to an input parameter. that will take no effect on the object created.
animalName = name;
numberOfLegs = legs;
}
public String getName(){
return animalName;
}
public int getLegs(){
return numberOfLegs;
}
public boolean isAnimal(){ //boolean function needs a return type too!!
return true;
}
public boolean isCarnivorous(){
return true;
}
public abstract String getHello(); // an abstract method has same requirement as a normal method besides the abstract modifier. it will need a return type. And it ends with a semicolon
}
public class Cat1 extends Animal1{
public Cat1(final String name){
super(name, 4); //use super to call parent constructor
}
#Override
public String getHello(){
return "Meow";
}
}
public class Dog1 extends Animal1{
public Dog1(final String name){
super(name, 4);
}
#Override
public String getHello(){
return "Woof";
}
}
First, it looks like a few of your methods are declared as classes. I assume you wanted to make them abstract methods. They need to be changed to:
public abstract String getHello();
Note that abstract methods can only be declared in an abstract class. So, you need to redefine Animal1 as abstract.
public abstract class Animal1
Next, when you implement the abstract method, you define it as
public String getHello()
If you are using an IDE like Eclipse it will automatically offer to generate this method.
Finally, when using your constructor in your child classes like Cat1, you are trying to set "name" as if it was a static variable and bypassing the constructor you already had set for Animal1. The best way to correct this is to change the constructor in Cat1 and Dog1 to call the super constructor.
public Cat1(String name){
super(name);
}

Beginner Java OOP

I am developing a simple Dog class to create dog objects and display the results.
Dog
_________
int - size
String - breed;
String - name;
__________
Dog(int, String, String)
bark()
bark(int)
toString(): String
print()
I have made the class successfully using getters and setters but my problem is the toString and print methods. I understand the toString method should return a string with the dog details but don't know how to print them.
I could in theory print it like this:
Dog a = new Dog ();
String details = a.toString();
System.out.println(details);
But this isn't how it's specified in the UML spec.
Should the toString method call the print method itself?
and if so, how?
Dog class:
class Dog{
private int size;
private String breed;
private String name;
//Create getter and setter methods:
public void setName (String name){
this.name = name;
}
public void setSize (int size){
this.size = size;
}
public void setBreed (String breed){
this.breed = breed;
}
public int getSize () {
return this.size;
}
public String getBreed () {
return this.breed;
}
public String getName () {
return this.name;
}
public void bark () {
System.out.println("Ruff! Ruff!");
}
public void bark (int amtOfBarks){
for (int i = 0; i < amtOfBarks; i++){
System.out.print("Ruff! Ruff! ");
}
}
public String toString () {
return "Name: "+this.name+"\nBreed: "+this.breed+"\nSize: "+this.size;
}
}
Main Method:
class TestDog {
public static void main (String [] args){
Dog rex = new Dog();
rex.setName("Rex");
rex.setBreed("poodle");
rex.setSize(1);
rex.toString();
rex.bark(3);
}
}
From your Class structure diagram, the print() method should call System.out.println(this);.
Note : The toString() will be called implicitly. in System.out.println
Agree with klemenp.
write your toString() method as follows:
#override
public String toString () {
return "Name: "+this.name+"\nBreed: "+this.breed+"\nSize: "+this.size;
}
and it will be implicitly called when you print the Object:
Edit to your code :
class TestDog {
public static void main (String [] args){
Dog rex = new Dog();
rex.setName("Rex");
rex.setBreed("poodle");
rex.setSize(1);
//rex.toString();
System.out.println(rex);
rex.bark(3);
}
}
The toString() method should not call the print() method. It should be the other way around.
Override toString() and call it from the print() method.
#Override
public String toString()
{
return "details";
}
public void print()
{
System.out.println(this.toString()); // same as System.out.println(this);
}
in class Dog
public String toString(){
return "details of dog";
}
so you can:
a = new Dog();
....
System.out.println(a);
from the doc of toString
Returns a string representation of the object. In general, the toString method returns a string that "textually represents" this object. The result should be a concise but informative representation that is easy for a person to read. It is recommended that all subclasses override this method.
so to show your own details you have to override this method. a casual example is given here
public String toString(){
String s = /// add your detials
return s;
}
now from the code where you are using dog instance print dog.toString()
Creating a dog in this case is :
Dog a = new Dog (120, "breedname", "name");
In order to print the details you need getters,
in a create a get function like
getBreed(){
return breed; }
in dog, then to print you use:
System.out.println(a.getBreed());
in Class Dog write toString() as follows :
#Override
public String toString() {
return "String describing the details about Dog class";
}
Here #Override annotation is required, because every class has Default toString() method inherited from Object class....
To represent your object as String you have to override toString() method.
It is usually done as below (Eclipse as an example can generate it for you, using fields you will tell)
class Dog {
private int size;
private String breed;
private String name;
//constructors, methods, getters and setters
#Override
public String toString() {
return "Dog [size=" + size + ", breed=" + breed + ", name=" + name
+ "]";
}
}
Then you may use your instance object directly in System.out.println() and you will get String representation. You do NOT need to do as you said String details = a.toString(); and only then use it.
Dog dogInstance = new Dog(21, "Dog Breed", "Dog Name");
System.out.println(dogInstance);
As a result will be:
Dog [size=21, breed=Dog Breed, name=Dog Name]

java- calling sub-class from a list

I have this code:
public abstract class animal {
public final static int elephent = 1;
public final static int dog = 2;
and two sub-classes:
public class elephant extends animal {
public final static int type = animal.elephent;
public elephant (String name){
super(name);
}
}
public class dog extends animal {
public final static int type = animal.dog;
public dog (String name){
super(name);
}
}
now, say I have a list of Chars with the letters E- elephant and D- dog.
and an empty list of animals class of the same size.
and for every char on the first list I want to create a new instance of the right animal.
example: ["d","e","d"]
would give me a list of: [new dog, new elephant, new dog]
hope I made myself clear,
thanks in advance for the help.
This design is not optimal. You are indicating the type with an integer variable, which really is not a good idea.
First improvement: Make the type indication an enum.
public enum AnimalType {
ELEPHANT, DOG
}
Now add a type field in your animal class:
public abstract class Animal {
private final AnimalType type;
private final String name;
protected Animal(AnimalType type, String name) {
this.type = Objects.requireNonNull(type);
this.name = Objects.requireNonNull(name);
}
// more fields and methods here
}
An elephant then looks like that (dog is similar):
public class Elephant extends Animal {
public Elephant(String name) {
super(AnimalType.ELEPHANT, name);
}
// more fields and methods here
}
The main disadvantage: Each time you add a new animal type, you must add a new class and add a type to the enumeration. This is not the best design. Additionally, the type enum is not really needed, as the sub types already hold the type information
An instance of class Elephant is an elephant (dog the same). It does not need the type field.
Second improvement: Delete the type indication completely. No integers, no enums. Just have the abstract class and the sub classes.
Now your question, how to get the correct instance from any character input. This is called a mapping. You want to map
the character 'E' to the class Elephant.
the character 'D' to the class Dog.
This can be achieved by a Java Map:
Map<Character, Class<? extends Animal>> charToAnimal = new HashMap<>();
charToAnimal.put('E', Elephant.class);
charToAnimal.put('D', Dog.class);
Class<? extends Animal> animalClass = charToAnimal.get('E');
String name = ...;
Animal animal = animalClass.getConstructor(String.class).newInstance(name); // will be an Elephant instance
This map should be maintained in any class you need that behavior, or maybe in the main method if you are just learning how to do that.
Note, that I used a Java mechanism called reflection, just to create an instance, as there is no other generic way to handle the instantiation.
Another approach would be a method that does the same:
public Animal createAnimal(char c, String name) {
if (c == 'E') {
return new Elephant(name);
} else if (c == 'D') {
return new Dog(name);
} else {
throw new IllegalArgumentException(c);
}
}
Either way, you have to add not only a ne animal sub class, but you have to add an entry into the map (see above) or an if branch to the method.
EDIT, as I thought again over this scenario.
You could go with the enum approach and put the class instantiation into this enum. Take the animal classes as above and the following type enum (not checked):
public enum AnimalType {
ELEPHANT('E', Elephant.class),
DOG('D', Dog.class);
private static final Map<Character, Class<? extends Animal>> CHAR_TO_ANIMAL = new HashMap<>();
AnimalType(char c, Class<? extends Animal> animalClass) {
CHAR_TO_ANIMAL.put(c, animalClass)
}
public Animal createAnimal(char c, String name) {
if (c == 'E') {
return new Elephant(name);
} else if (c == 'D') {
return new Dog(name);
} else {
throw new IllegalArgumentException(c);
}
}
}
So one of the things you may want to consider is a switch-case statement. So in Java, you could do something like this:
// get a char from the list.
char animal;
switch(animal)
{
case'e':
Elephant varName = new Elephant("Dumbo");
newList.add(varName);
break;
}
I've not included everything here, but this should get you started. You will need to look up iterating (looping) through a data structure.
I will be honest, it's been a while since I've written any Java, but this is one way you could do this. There are other ways to do this as well, such as using an if block as well.
Hope this helps.
I think what u need is an static factory method returns an instance.Here is one way of doing it.
Abstract Class:
public abstract class animal {
public final static char elephent = 'E';
public final static char dog = 'D';
}
Elephant Class:
public class Elephant extends Animal {
private char myType;
private String name;
public Elephant(char type, String name) {
super();
this.myType = type;
this.name = name;
}
public String getName() {
return name;
}
public void setName(String name) {
this.name = name;
}
public char getMyType() {
return myType;
}
public void setMyType(char myType) {
this.myType = myType;
}
}
Dog Class:
public class Dog extends Animal {
private char myType;
private String name;
public Dog(char type, String name) {
super();
this.myType = type;
this.name = name;
}
public String getName() {
return name;
}
public void setName(String name) {
this.name = name;
}
public char getMyType() {
return myType;
}
public void setMyType(char myType) {
this.myType = myType;
}
}
Factory Class:
public class FactoryMethod {
static char getAnimalIndex(char type){
switch (type) {
case 'E':
case 'e':
return Animal.ELEPHANT;
case 'D':
case 'd':
return Animal.DOG;
default:
throw new IllegalArgumentException(String.valueOf(type));
}
}
public static Animal getInstance(char type, String name){
Animal myCategory = null;
switch (getAnimalIndex(type)) {
case Animal.ELEPHANT:
myCategory = new Elephant(type,name);
break;
case Animal.DOG:
myCategory = new Dog(type,name);
break;
}
return myCategory;
}
}
Usage:
if u need to use Animal class index or as u with the character from the list this factory method works.
To get instance:
//using Animal index
FactoryMethod.getInstance(Animal.ELEPHANT,"Elephant");
FactoryMethod.getInstance(Animal.DOG,"Dog");
//using characters in list
FactoryMethod.getInstance('character_in_list_here',"Name OF The Animal Here");
Since it is a static method u can use without using FactoryMethod instance.
I hope this is what u needed.

Categories