Why polymorphism doesn't play a role? [duplicate] - java

This question already has answers here:
why java polymorphism not work in my example
(3 answers)
Closed 6 years ago.
This output make me confused. Present Code First:
public class Animal{
int age;
public Animal(int age){
this.age = 0;
}
public int getAge(){
return age;
}
}
public class Wolf extends Animal{
int age;
Wolf(int age){
super(age);
this.age = age;
}
}
public class MainTest {
public static void main(String[] args){
Wolf wolfExample = new Wolf(2) ;
System.out.println("Age = " + wolfExample.getAge());
}
}
The output is:
0
My expected output is:
2
through debug this program it seemed that wolfExample.getAge() return the age of its parent not itself, why? base on polymorphism here should return the age of wolf, I will appreciate if you can give me some guide.
Note: Currently, I find inheritance is far difficult than what I think before.

Polymorphism exists for methods, not for fields. Therefore getAge(), which is only implemented in the Animal class, returns the member of the Animal class.
If you override getAge() in the Wolf class, i.e. add a
#Override
public int getAge() {
return age;
}
you'll get the value of the Wolf class member.
That said, it doesn't make sense to have an age member in both the base class and sub-class. If it's a property common to all Animals, it should only be in the Animal class.
So your Wolf class will become :
public class Wolf extends Animal {
Wolf(int age) {
super(age);
}
}
And your Animal constructor doesn't make sense. You should assign the passed age argument to the member of the class :
public Animal(int age) {
this.age = age;
}

You don't need "int age" in Wolf class. By commenting it out, you may get your desired output.
public class Animal{
int age;
public Animal(int age){
this.age = age;
}
public int getAge(){
return age;
}
}
public class Wolf extends Animal{
//int age;
Wolf(int age){
super(age);
//this.age = age;
}
}

Related

Java: Issue building a zoo using inheritance

I am new to Java and I'm having an issue with inheritance. I'm working through an activity where I have a parent class (Animal) and child classes (Giraffe in this instance) which inherits the fields of the parent class. I was instructed to have a default constructor and a constructor that accepts parameters in both instances of the parent and child classes.
The issue that I'm encountering is that when I run printInfo() it is returning the default for species in the parent's default constructor ('species') and not the child class ('giraffe'). I had assumed that the Giraffe child class would inherit this parent class method, but it seems that something's not quite right here.
(Note that each of my classes are separate files)
Any assistance or pointers would be greatly appreciated.
// Parent class:
public class Animal {
String name;
String species;
int age;
// default constructor
public Animal() {
name = "name";
species = "species";
age = 0;
}
// constructor w/ parameters
public Animal(String name, String species, int age){
this.name = name;
this.species = species;
this.age = age;
}
// method for printing out animal info
void printInfo() {
System.out.println(name + ", " + species + ", " + age);
}
}
// Child class:
public class Giraffe extends Animal {
String species = "giraffe";
// default giraffe constructor
public Giraffe() {
super();
name = "Errol";
age = 0;
}
// giraffe constructor with parameters
public Giraffe(String name, int age) {
super();
this.name = name;
this.age = age;
}
}
// Main class (calls printInfo method from Animal parent class)
public class ZooBuilder {
public static void main(String[] args) {
Giraffe one = new Giraffe("Mark", 23);
one.printInfo();
}
}
Prints: *Mark, species, 23*
Change the Giraffe constructor to call the full constructor
public Giraffe(String name, int age) {
super(name, "Giraffe", age);
}
Change the default to also be like the above

Creating common method for two classes not using inheritance in java

I'm just wondering if there is any way to create two classes that aren't related but have the same implementation of method. I know there are interfaces and static methods but it seems like they are good only when you have static field in class. Is this possible to do that kind of thing when method uses field that is specific to exact object?
I know it's a bad practice writing code like this but I'm just curious.
EDIT:
I mean something like this:
public class Person implements MakingOlder {
private int age;
}
public class Cat implements MakingOlder {
private int age;
}
public interface MakingOlder {
public static void makeOlder() {
this.age += 2;
}
}
I don't want to make common base class for Person and Cat and interface is not working. I'm trying to avoid writing the same implementation twice and copying the code.
Sure, it's called "composition + delegation", and it's often a good practice to replace inheritance by this :
https://en.wikipedia.org/wiki/Composition_over_inheritance
public class Person implements AgingObject {
private int age;
private AgingBehavior agingBehavior;
void makeOlder() {
agingBehavior.makeOlder(this);
}
//(...)
}
public class Cat implements AgingObject {
private int age;
private AgingBehavior agingBehavior;
void makeOlder() {
agingBehavior.makeOlder(this);
}
//(...)
}
public class AgingBehavior {
void makeOlder(AgingObject agingObject) {
agingObject.setAge(agingObject.getAge() + 2);
}
}
public interface AgingObject {
int getAge();
void setAge(int age);
}
...or you can use default implementation in Java 8+...
public interface MakingOlder {
public default void makeOlder() {
setAge(getAge() + 2);
}
int getAge();
void setAge(int age);
}
and of course your Person and Cat implements MakingOlder...
Probably your interface is not working because you are trying to implement a method within the interface:
public static void makeOlder() {
this.age += 2;
}
In order to make it work, try to add the default keyword so that it looks like:
default Integer makeOlder(Integer age) {
age += 2;
return age;
}
Then the class, which implements that interface, will just need to contain something like:
public class Dummy implements AA {
Integer age;
public Integer getAge() {
return age;
}
public void setAge(Integer age) {
this.age = age;
}
}
To test the result you can call something like:
Dummy d = new Dummy();
d.setAge(d.makeOlder(7));
System.out.println(d.getAge());
d.setAge(d.makeOlder(d.getAge()));
System.out.println(d.getAge());

parent and child same variable name,inheritance

if i have a class Fish
public class Fish {
int numberOfFins;
int age;
public Fish(int age){
this.age=age;
}}
and class Shark that extends the Fish class
public class Shark extends Fish{
private int age;
public Shark(int age) {
super(age);
this.age=age;
}}
what age variable is accessed trough keyword this - is it of parent or from child class?
Thanks in advance?
Which age you access depends on the type of the thing you use to access it. this always has the type of the class the method or constructor belongs to — that is, in Fish's methods/constructors, this is of type Fish. In Shark's methods/constructors, this is of type Shark. (There's only one object, which combines the features of Fish and Shark [yes, it really has two separate fields with the same name]; what we're talking about is the type of the reference to it.)
(Note that this is different for instance variables (like age; aka "fields") than it is for instance methods. In Java, methods are polymorphic, instance variables are not.)
So within Fish code, this.age is Fish's age. Within Shark code, this.age is Shark's age.
E.g.:
public class Fish {
int numberOfFins;
int age;
public Fish(int age) {
this.age=age; // Sets Fish#age
}
}
public class Shark extends Fish {
private int age;
public Shark(int age) {
super(age);
this.age=age; // Sets Shark#age
}
}
This doesn't only apply to this, it applies to variables as well. Look at main below (and notice that I set the two ages to different values; Shark's age is twice Fish's age):
class Fish {
int numberOfFins;
int age;
public Fish(int age) {
this.age = age; // Sets Fish#age
}
}
public class Shark extends Fish {
private int age;
public Shark(int age) {
super(age);
this.age = age * 2; // Sets Shark#age
}
public static void main(String[] args) {
Shark s = new Shark(10);
Fish f = s;
System.out.println(f.age); // 10
System.out.println(s.age); // 20
}
}
age will be inhereted from Fish but since you are decalring another variable with name "age" the inhereted variable will be hidden so what you will be having in your current object which is referenced by this is the variable declared in Shark
this
Within an instance method or a constructor, this is a reference to
the current object — the object whose method or constructor is being
called.
public Fish(int age){
this.age=age; / the one is Fish
}
Similarly in the other class, you have a member with the same name, which would be referenced in its c'tor :
public Shark(int age) {
super(age);
this.age=age; // the one in class Shark
}

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.

java default access modifiers

I am a complete beginner in java, so please forgive me if this question is not up to the standard of this website:
class person{
String name;
int age;
}
class teacher extends person{
person s1=new person();
teacher t1=new teacher();
t1.age=56;
}
Here I am trying to access the variable age and name of class to assign them values person, which happens to be the super class of person. But the compiler is giving error. I even tried to make the name variable and age variable as public. But the compiler is still reporting an error. I want to know the reason why I can't access superclass variable in subclass directly and assign values to them.
You are not allowed to write arbitrary code directly within a class body. The closest thing to what you have written is
class teacher extends person{
person s1=new person();
teacher t1=new teacher();
{
t1.age=56;
}
}
This is called the instance initializer block.
In general, it is not a good idea to access variables directly. Consider using something like the code below.
Test driver
package com.example.input;
public class TestPeople {
public static void main(String[] args) {
Person s1 = new Person();
s1.setName("student 1").setAge(19);
Teacher t1 = new Teacher("Dr. Fun",0);
t1.setAge(56);
System.out.println("Student " + s1.getName() + ", " + s1.getAge());
System.out.println("Teacher " + t1.getName() + ", " + t1.getAge());
}
}
Class Person
package com.example.input;
public class Person {
private String name;
private int age;
public Person() {};
public Person(String aName, int anAge) {
setName(aName).setAge(anAge);
}
public String getName() {return name;}
public int getAge() {return age;}
public Person setName(String aName) { name = aName; return this;}
public Person setAge(int anAge) { age = anAge; return this;}
}
Class Teacher
package com.example.input;
public class Teacher extends Person {
public Teacher() {
super();
}
public Teacher(String aName, int anAge) {
super(aName, anAge);
}
}
Actually you are making an assignment of variable of external class in existing class body which is not legal.Make the assignment in a method or constructor or in a anonymous block.
class person{
String name;
int age;
}
class teacher extends person{
person s1=new person();
teacher t1=new teacher();
// t1.age=56; Error here
public teacher()
{
t1.age=56;
}
//or method
public void setAge()
{
t1.age=56;
}
}
do whatever suits your program and you.

Categories

Resources