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
}
Related
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
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;
}
}
Superclass
public class food {
private String name;
public food( String name){
this.name = name;
}
public void foodName() {
System.out.println("This is "+name);
}
}
Subclass
public class Bacon extends food {
private String name;
public Bacon (String name) {
super(name);
this.name=name;
}
public void foodName() {
System.out.println("This is a food named " +name);
}
}
For the variable name of the subclass Bacon to work in the overriden method, is this the best practice or are there better ways to do it?
public Bacon(String name){
super(name);
this.name=name;
}
In class Bacon, the declaration of name hides the declaration of name in Food class, and all references to name in Bacon class refer to the Bacon.name not Food.name.
So please go through the Inheritance chapter again.
There is no need of name declaration again in Bacon class. Remove the declaration, since it is extending Food class, it will have name property.
To access name in the child classes add access specifier to the name property as protected like
protected String name; //inherited classes can have access to this property
Also modify the constructor
public Bacon (String name) {
super(name);
// (removed) this.name=name;
}
In this case more logical will be to mark name variable as protected, it will allow subclasses and package members to access it.
Superclass
public class food {
protected String name;
public food( String name){
this.name = name;
}
public void foodName() {
System.out.println("This is "+name);
}
}
And remove duplicate name variable in subclass and just use constructor if superclass
public class Bacon extends food {
public Bacon (String name) {
super(name);
}
public void foodName() {
System.out.println("This is a food named " +name);
}
}
There is no overriding of variables in Java, and you can't access a private variable from a superclass in a subclass in general; so what you have is two separate variables called name.
If you want your subclass to have access to the variable then make it protected in the superclass:
public class food {
protected String name;
//...
}
If you really want to restrict access, and the subclass only needs to use the variable (not modify it), then you should uses a getter method.
public class food {
private String name;
protected String getName() {
return name;
}
//...
}
You subclass can then call getName() instead of using name.
Here is the Assignment:
Design and implement a class representing a Person along with 3 subclasses using the following guidelines:
a.Create a class named Person and its three subclasses named Employee, Student, Retired.
b.The Person has the following data fields: name, year_of_birth, isStudying, and isEmployed. It also has methods for setting and getting the values of each of the fields along with a method to calculate the current age and display the status of a Person. A constructor that sets the isStudying and isEmployed fields to false is also included in the Person class. You are welcome to add additional data fields and methods if you like.
1.Finally, create a Java test class that simulates using your Person class. In your test class you should at a minimum: a) Construct 4 instances of a Person, b) print the names of your instances c) print the status of your instances based on the values of their age, isStudying and isEmployed attributes.
public class Person2 {//begin class
//declare variables
String name;
int year_of_birth;
boolean isStudying;
boolean isEmployed;
int age;
public Person2(String name, int year_of_birth, boolean isEmployed, boolean isStudying, int age){//begin constructor
this.name = name;
this.year_of_birth = year_of_birth;
this.isEmployed = false;
this.isStudying = false;
this.age = age;
}//end constructor
public int getYear(){//get year method
return year_of_birth;
}//end method
public String getName(){//get name method
return name;
}//end method
public boolean getEmployed(){//get employed method
return isEmployed;
}//end method
public boolean getStudying(){//get employed method
return isStudying;
}//end method
public int getAge(){//get year method
age = 2014 - year_of_birth;
return age;
}//end method
public void setName(String name){//set name method
this.name = name;
}//end method
public void setYear (int year){//set year method
this.year_of_birth = year;
}//end method
public void setEmployed(boolean employed){//set employed method
this.isEmployed = employed;
}//end method
public void setAge (int age){//set year method
this.age = age;
}//end method
public static void main(String[] args) {
// TODO code application logic here
}
}
class Student extends Person2 {//begin class
public Student(String name, int year_of_birth, boolean isEmployed, boolean isStudying, int age){//begin constructor
this.name = name;
this.year_of_birth = year_of_birth;
this.isEmployed = isEmployed;
this.isStudying = isStudying;
this.age = age;
}//end constructor)
#Override
public int getYear(){//get year method
return year_of_birth;
}//end method
#Override
public String getName(){//get name method
return name;
}//end method
#Override
public boolean getEmployed(){//get employed method
return isEmployed = false;
}//end method
#Override
public boolean getStudying(){//get employed method
return isStudying = true;
}//end method
#Override
public int getAge(){//get year method
age = 2014 - year_of_birth;
if (age > 30){
System.out.println("Person is not a student");
}
return age;
}//end method
}
This code obviously isn't complete I am getting hung up on this constructor error. It says "actual and formal arguments differ in length".
You problem is that you are not invoking the super constructor Person2. Your constructor in Student is trying to invoke a the default constructor (with no arguments) of Person2, which doesn't exist.
You only have one constructor in Person2, and should call that constructor from the constructor of Student:
public Student(String name, int year_of_birth, boolean isEmployed, boolean isStudying, int age) {
super(name, year_of_birth, isEmployed, isStudying, age);
}
This also means you don't need to repeat all of that initialisation code twice.
You also shouldn't be repeating all the methods in Student that are in Person2. If you take them out, Student will inherit them anyway. That's the whole point in extending the class in the first place. You should only override a method like that if you don't want the inherited behaviour, but want some Student specific behaviour instead.
When extending any functionality you should try to use that functionality...
Your class Student extends Person2 but does it use anything from Person2?
Why do you override all methods and provide identical functionality in your subclass???
In the following java code
public class Person {
int age = 18;
}
class Student extends Person {
public Student() {
this.age = 22;
}
public static void main(String[] args) {
Student student = new Student();
student.doSomthing();
}
void doSomthing() {
System.out.println(this.age);
System.out.println(super.age);// Here is something weird, at least for me till rightNow()
}
}
Why the super.age value is 22 , the same value as the sub-class's age value, Isn't it supposed to be 18;
Any help is appreciated.
Thanks in advance.
Age is a field in the super class. In the constructor of the subclass, when you say this.age = 22, you are updating the instance variable in the super class.
Try the following ... I dont have a compiler handy but i think it might do what you are expecting.
public class Person {
int age = 18;
}
class Student extends Person {
int age; // Hides the super variable
public Student() {
this.age = 22;
}
public static void main(String[] args) {
Student student = new Student();
student.doSomthing();
}
void doSomthing() {
System.out.println(this.age);
System.out.println(super.age);
}
}
this is behaving as you would expect. You haven't declared an 'age' member of Student, so this.age naturally references 'age' defined in the superclass.
The code below will provide the behaviour you are expecting (although shadowing variables like that is often a very bad idea).
public static class Person {
int age = 18;
}
public static class Student extends Person {
int age = 18;
public Student() {
this.age = 22;
}
void doSomthing() {
System.out.println(this.age);
System.out.println(super.age);
}
}
No, that is correct. In the constructor, you are overriding the super class's age. You could instead do something like this:
public class Person {
public int getAge() {
return 18;
}
}
class Student extends Person {
public Student() {
}
#Override
public int getAge() {
return 22;
}
public static void main(String[] args) {
Student student = new Student();
student.doSomthing();
}
void doSomthing() {
System.out.println(this.getAge()); //22
System.out.println(super.getAge()); //18
}
}
Student inherits age from parent, so there is no difference between age and super.age
No, what is happening is correct. When you create a subclass (Student is a subclass of Person), that subclass inherits all of the fields (variables) from the superclass. However, there is only one set of variables: there is only one value for age, even though it is inherited. In other words, when a class inherits a field, it doesn't create a new copy of it - there is only one copy per student.
In this source, this and super are the same instance variable because you define it in the super class an inherited in the subclass.
When you create your Student you initilize it to 22 and that's it.
Nothing strange, it's behaving correctly. Class Student doesn't have a private variable age, which would overwrite parents variable.
You're setting age in your Student class, but the parent is the one declaring age and they share the same variable - therefore, it makes sense that the value was modified. Overriden methods would be different, however.