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
Related
What I should change to print the name of chair, which is chairNumber1?
public class Employee {
private Chair s;
Employee(Chair s) {
this.s = s;
}
void showData() {
System.out.println("Name of chair : " + s);
}
}
public class Chair {
}
public class Hlavna {
public static void main(String[] args) {
Chair s = new Chair("chairNumber1");
Employee c1 = new Employee(s);
c1.showData();
}
}
Why when I want to print name of the Chair, which is chairNumber1, Java prints on console the address of chairNumber1, but not it's name?
You must be already aware of the fact that every class in Java inherits a class called Object by default. This class has a method toString() which returns a string consisting of the name of the class of which the object is an instance, the at-sign character `#', and the unsigned hexadecimal representation of the hash code of the object.
When you use System.out.println("Name of chair : " + s);, it will call s.toString() but since you haven't provided your own implementation of toString() inside class Chair, it will call the toString() method of class Object which is the default superclass of class Chair. This is why you see the value which you think as the address of chairNumber1.
To get your desired String, you need to override the toString() method something like:
public class Chair {
private String name;
public Chair(String name) {
this.name = name;
}
public String toString() {
return name;
}
}
define a method inside your chair class that returns the name or override the toString method.
example:
public class Chair{
private String chairName;
Chair(String chairName){
this.chairName = chairName;
}
public String toString(){
return chairName;
}
}
now inside showdata() call toString():
void showData(){
System.out.println("Name of chair : " + s.toString());
}
There are a couple of things going on here.
You have created a chair object in your main method of your Hlavna class. To this Chair object you have provided an argument, although from the code above Chair does not take an argument.
In the same way that you have made the Employee class take an argument of chair, you should take the Chair take an argument of name, like so:
public class Chair
{
private String name;
Chair(String chairName)
{
this.name = chairName;
}
}
Now this isn't enough. When you print any Java object, under the hood what is really happening is the object's toString method is called. By default this prints the object's address, but you can override that by implementing the method yourself, like so:
public class Chair
{
private String name;
Chair(String chairName)
{
this.name = chairName;
}
public String toString()
{
return this.name;
}
}
Now, when you print a chair object it will call the Chair object's implementation of toString, which here returns the chair's name.
Your employee class is correctly printing the "toString()" method of the chair that you pass to it as you construct it, but currently that looks like an address. If you change the Chair object to the above code, that will instead print the chair name, which is what you are after.
The full code would look like this:
public class Employee
{
private Chair s;
Employee(Chair s)
{
this.s = s;
}
void showData()
{
System.out.println("Name of chair : " + s);
}
}
public class Chair
{
private String name;
Chair(String chairName)
{
this.name = chairName;
}
public String toString()
{
return this.name;
}
}
public class Hlavna
{
public static void main(String[] args)
{
Chair s = new Chair("chairNumber1");
Employee c1 = new Employee(s);
c1.showData();
}
}
public class Chair {
private String name;
public Chair(String name) {
this.name = name;
}
#Override
String toString() {
return name;
}
}
public class Animal {
String name;
Animal(String name) {
this.name = name;
}
Animal() {
this(makeRandomName());
}
static String makeRandomName() {
int x = (int) (Math.random() * 5);
String name = new String[] {"Fluffy", "Fido","Rover", "Spike","Gigi"}[x];
return name;
}
public static void main (String [] args) {
Animal a = new Animal();
System.out.println(a.name);
Animal b = new Animal("Zeus");
System.out.println(b.name);
}
}
No, for the Animal() constructor that calls the other constructor (using this(makeRandomName());), super() won't be added. It would be added only to the Animal(String name) constructor.
This means, of course, that both constructors will end up executing the super class's constructor (i.e. Object's constructor).
A super() call will be inserted unless there is a super() or this() call already explicitly present.
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.
class Person
{
String name = "No name";
public Person(String nm)
{
name = nm;
}
}
class Employee1 extends Person
{
String empID ="0000";
public Employee1(String id)
{ // Line 1
empID = id;
}
}
public class EmployeeTest
{
public static void main(String[] args) {
Employee1 e = new Employee1("4321");
Person p = new Person("Hello");
System.out.println(e.empID);
}
}
I get compilation error saying constructor Person in class Person cannot be applied to given types; required String found no arguments but I am passing arguments for both the parent and the child class when I create new object in main method. Unable to figure out why compilation error?
You need to properly create the parent class, passing it a name as the Person construtor requires:
public Employee1(String id) {
super("person name"); // create the parent
empID = id;
}
Or maybe something like:
public Employee1(String id, String name) {
super(name); // create the parent
empID = id;
}
public static void main(String[] args) {
Employee1 e = new Employee1("4321", "Hello");
// ...
}
Because constructor in child class implicitly calls the parameter-less constructor of it's immediate super class only if the default constructor does not explicitly call a superclass constructor so
public Employee1(String id)
{ // Line 1
empID = id;
}
will try to call constructor in super class as you have not called it explicitly so you can say your code will be like this
public Employee1(String id)
{
super(); // Line 1
empID = id;
}
but in you parent class there is no "no argument" constructor, so it is giving error like this.
The implicit super constructor Person() is undefined.
So you must explicitly invoke its parent constructor.
On the constructor of employee you must call first the constructor of person as in super(name); and then initialize the subclass
class Employee1 extends Person
{
String empID ="0000";
public Employee1(String id, String name)
{ // Line 1
super(name);
empID = id;
}
}
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.