How to correctly configure multiple constructors? - java

I'm doing an assignment based around inheritance and I have created 2 constructors that are suppose to do different things. One constructor does not have any parameters and should produce a pre-defined value, the other constructor has 2 parameters which consist of a name and an age of types String and int. I have somehow reconfigured the two constructors so that they both do not produce what they should be. Here is the classes that these constructors are invoked in:
Animal (super class)
abstract public class Animal implements Comparable<Animal>
{
int age;
String name;
Animal(String name, int age)
{
this.age = age;
this.name = name;
}
Animal()
{
this("newborn", 0);
}
public int getAge()
{
return age;
}
public void setName(String newName)
{
name = newName;
}
String getName()
{
return name;
}
}
Carnivore
public class Carnivore extends Animal
{
Carnivore(String name, int age)
{
this.age = age;
this.name = name;
}
Carnivore()
{
super();
}
#Override
public int compareTo(Animal o)
{
//To change body of generated methods, choose Tools | Templates.
throw new UnsupportedOperationException("Not supported yet.");
}
}
Wolf
public class Wolf extends Carnivore
{
String name;
int age;
Wolf(String name, int age)
{
this.name = name;
this.age = age;
}
Wolf()
{
super();
}
String getName()
{
return name;
}
}
Main method
System.out.println("************1st constructor of Wolf************");
Wolf wolfExample = new Wolf("Bob", 2) {};
System.out.println("Name = " + wolfExample.getName());
System.out.println("Age = " + wolfExample.getAge());
System.out.println("************2nd constructor of Wolf************");
Wolf newWolf = new Wolf();
System.out.println("Name = " + newWolf.getName());
System.out.println("Age = " + newWolf.getAge());
Actual Output
************1st constructor of Wolf************
Name = Bob
Age = 0
************2nd constructor of Wolf************
Name = null
Age = 0
Expected Output
************1st constructor of Wolf************
Name = Bob
Age = 2
************2nd constructor of Wolf************
Name = newborn
Age = 0
The ages are returning their default value and the name for the second constructor is also returning null but I'm not too sure why. This is my first time working with multiple constructors so I'm a little confused as to ow it works so any help would be much appreciated, thanks.

Your base class seems correct, but you need to change your implementations.
Your Wolf and Carnivore constructors should be:
Wolf(String name, int age)
{
super(name, age);
}
Reason being, you are setting the local instance variables for each type, but calling getAge() method of the super class - this is getting the super's value of age, whose's value has not actually been assigned anywhere, and is given a default value of 0. This goes the same for name, which defaults to null.
You need to call super with the passed variables, and do not need to redefine them for each extended object.

Related

How can I make an object using another object in Java?

I am defining the characteristics of a Dog class which contains instance data defining their name and age, making constructors for this data, setter-getter methods, etc. I also have a method which returns the value of "dog years" (aka, seven years times a human year that passes for their equivalent age). I have a driver class, Kennel, which main method instantiates and updates these Dog objects, and prints them out.
In the Kennel class, one of my last statements you can see a comment that says ""INQUIRE AT SOME POINT".
I.e: //Dog dog3 = dog2.setName("Krypto");
In the comment, I have tried to make a new Dog object called "Kryto" while assigning the rest of the dog2 object's data to it via a setName method. In other words, I want my dog3 object to have all of dog2's characteristics with the exception of the name.
What would be the way to accomplish this? I understand that I can't use an object as a parameter, right?
Here's my code for the two classes below:
Kennel (Driver):
public class Kennel {
//instance data
int age;
public static void main(String[] args) {
//dog objects
Dog dog1 = new Dog("Bear", 3);
Dog dog2 = new Dog("Bella", 7);
//calling the method required to calculate the dog's human years, so that when I print these objects out, they actually have their traits
//(that being, their "dogman" age.
dog1.calcDogmanYears();
dog2.calcDogmanYears();
//output
System.out.println(dog1);
System.out.println(dog2);
dog2.setName("Krypto");
//Dog dog3 = dog2.setName("Krypto"); //INQUIRE AT SOME POINT
System.out.println(dog2);
}
}
Dog:
public class Dog {
//instance data
String name;
int age;
//constructor (normal) to allow objects to have values by default (i.e. no requirement of forcing parameters down the methods from the driver class)
public Dog() {
name = "";
age = 0;
return;
}
//constructor, keep in mind for future reference, that I used different variables to allow the constructor to be overloaded in a driver class to
//follow Chapter 4's constructor Java syntax. We could've overloaded the constructor with formal parameters of the same name as the instance data
//with the "this.(insert variable here)" modifier. I did this for shits and giggles.
public Dog(String name, int age){
this.name = name;
this.age = age;
return;
}
//method to convert dog to human years
public int calcDogmanYears() {
age = age * 7;
return age;
}
//setters and getters for name
public void setName(String name) {
this.name = name;
}
public String getName() {
return name;
}
//mutators and accessors for age}
public void setAge(int age) {
this.age = age;
}
public int getAge() {
return age;
}
public String toString() {
String result = "The name of the dog is " + name + ", and their age is " + age + " years old.";
return result;
}
}
One option would be to make the Dog class cloneable. Clone the original, then set the name appropriately.
Dog dog3 = dog2.clone();
dog3.setName("Krypto");
Kennel (Driver) class:
public class Kennel {
//instance data
int age;
public static void main(String[] args) throws CloneNotSupportedException {
//dog objects
Dog dog1 = new Dog("Bear", 3);
Dog dog2 = new Dog("Bella", 7);
//calling the method required to calculate the dog's human years, so that when I print these objects out, they actually have their traits
//(that being, their "dogman" age.
dog1.calcDogmanYears();
dog2.calcDogmanYears();
//output
System.out.println(dog1);
System.out.println(dog2);
dog2.setName("Krypto");
Dog dog3 = dog2.clone();
dog3.setName("Krypto"); //INQUIRE AT SOME POINT
System.out.println(dog2);
}
}
Updated Dog class:
public class Dog implements Cloneable {
//instance data
String name;
int age;
//constructor (normal) to allow objects to have values by default (i.e. no requirement of forcing parameters down the methods from the driver class)
public Dog() {
name = "";
age = 0;
}
// Overriding clone() method of Object class
public Dog clone() throws CloneNotSupportedException{
return (Dog) super.clone();
}
public Dog(String name, int age){
this.name = name;
this.age = age;
}
//method to convert dog to human years
public int calcDogmanYears() {
age = age * 7;
return age;
}
//setters and getters for name
public void setName(String name) {
this.name = name;
}
public String getName() {
return name;
}
//mutators and accessors for age}
public void setAge(int age) {
this.age = age;
}
public int getAge() {
return age;
}
public String toString() {
String result = "The name of the dog is " + name + ", and their age is " + age + " years old.";
return result;
}
}
output:
The name of the dog is Bear, and their age is 21 years old.
The name of the dog is Bella, and their age is 49 years old.
The name of the dog is Krypto, and their age is 49 years old.
You can define a new method in Dog class:
public Dog createTheSameAgeDog(String name) {
return new Dog(name, this.age);
}
Then call it:
Dog dog3 = dog2.createTheSameAgeDog("Krypto"); // creates the Dog (age 7, name "Krypto")

Variable within constructor is returning null?

I am doing a project based around the concepts of inheritance and have created a super constructor which has two variables within itself (String, int), this super constructor is then called within a sub constructor that inherited the super constructors class. I then use two methods to return the properties of those variables within the constructors. The age property is outputting fine but the String property is returning null. Here's the code:
Animal super-class
abstract public class Animal
{
int age;
String name;
Animal(String name, int age)
{
this.age = age;
this.name = name;
}
Animal()
{
this("newborn", 0);
}
public String getName() {
return name;
}
public void setName(String newName) {
name = newName;
}
}
Wolf sub-class
public class Wolf extends Carnivore
{
String name;
int age;
Wolf(String name, int age)
{
this.name = name;
this.age = age;
}
Wolf()
{
super();
}
public String getName()
{
return name;
}
public int getAge()
{
return age;
}
}
Main method class
public class Main {
public static void main(String[] args)
{
Wolf newWolf = new Wolf();
System.out.println("Name = " + newWolf.getName());
System.out.println("Age = " + newWolf.getAge());
}
}
Age is returning as 0 which is correct but System.out.println("Name = " + newWolf.getName()); seems to be returning null instead of "newborn". Any help on resolving this issue is appreciated thanks.
Update - I need the getName() method for another constructor that I haven't included in this example so is there a way to have them both exist?
The issue here is that you are defining your fields in the sub-class, you don't need to as they are inherited from the parent.
Your class has two sets of fields, one from the super (these are the ones set by your constructor, which is calling super() and the other from the child class (these are the ones returned by your getters, which are not initialized. the zero is int's default, not set either).
So simply remove the fields definition from the child class

Java Object set attribute default

class AStudent {
private String name;
public int age;
public void setName(String inName) {
name = inName;
}
public String getName() {
return name;
}
}
public class TestStudent2 {
public static void main(String s[]) {
AStudent stud1 = new AStudent();
AStudent stud2 = new AStudent();
stud1.setName("Chan Tai Man");
stud1.age = 19;
stud2.setName("Ng Hing");
stud2.age = -23;
System.out.println("Student: name="+stud1.getName()+
", age=" + stud1.age);
System.out.println("Student: name="+stud2.getName()+
", age=" + stud2.age);
}
}
How can I enhance the class AStudent by adding data encapsulation to the age attribute. If the inputted age is invalid, I want to print an error message and set the age to 18.
First, modify age so that it isn't public. Then add accessor and mutator methods (in the mutator, check for an invalid value - and set it to 18). Something like,
private int age;
public int getAge() {
return age;
}
public void setAge(int age) {
if (age < 0) {
System.err.println("Invalid age. Defaulting to 18");
age = 18;
}
this.age = age;
}
Then you could use it with something like setName
stud1.setAge(19);
and
stud2.setAge(-23);
And you could make it easier to display by overriding toString in AStudent like
#Override
public String toString() {
return String.format("Student: name=%s, age=%d", name, age);
}
Then you can print yor AStudent instances like
System.out.println(stud1); // <-- implicitly calls stud1.toString()
System.out.println(stud2);
You are using encapsulation for the name attribute. You could do the same for age.
class AStudent {
// ...
private int age;
public void setAge(int age) {
this.age = age;
if (age < 1) {
this.age = age;
}
}
}
The above code changes the age attribute to private so that access is restricted to the getter and setter. So you will also have to add a getter method and change TestStudent2 to use the new getter and setter.
What makes an age invalid? The above code assumes any value less than 1 is invalid.

java - can't create a constructor

class Human{
// declared instance variables
String name;
int age;
// instance method
void speak(){
System.out.println("My name is: " + name);
}
int calculateYearsToRetirement(){
int yearsLeft = 65 - age;
return yearsLeft;
}
int getAge(){
return age;
}
String getName(){
return name;
}
// so when I create an instance, i can't have constructor?
// error here
Human(int age){
age = this.age;
}
}
}
public class GettersAndReturnValue {
public static void main(String[] args) {
// error here because I created a constructor Human(int a)
Human human1 = new Human();
human1.name = "Joe";
human1.age = 25;
human1.speak();
int years = human1.calculateYearsToRetirement();
System.out.println("Years till retirements " + years);
int age = human1.getAge();
System.out.println(age);
}
}
I tried to create a constructor Human(int age) to practice 'this' keyword and to change the age from 25 to something else but I get an error because I have one Human class and one Human constructor. When I try to create an instance of Human Type in my main method, eclipse is asking me to remove the constructor
You've swapped the order in your assignment,
Human(int age){
age = this.age;
}
should be something like (don't forget to initialize name too)
Human(int age){
this.age = age;
this.name = "Unknown";
}
You're assigning the default value 0 to the passed in parameter. If you provide a constructor then the compiler will no longer insert the default constructor,
Human() {
this.age = 0;
this.name = "Unknown";
}
and you might as well add a constructor that takes the name,
Human(int age, String name) {
this.age = age;
this.name = name;
}
then you could call it (in main) like
Human human1 = new Human(25, "Joe");
// human1.name = "Joe";
// human1.age = 25;
You have to create a no parameter constructor, because when you are calling Human h = new Human();, you are calling a no parameter constructor.
Try doing this instead:
Human h = new Human(age);
When you create a non-empty constructor, the empty constructor will not be available anymore. You do can have more than one constructor, but if you want the no-argument constructor along with other, you will have to recreate it.
//Please, make it public for constructors
public Human(int age){
this.age = age; //this.age first, to receive the parameter age
}
public Human() {} //Empty constructor. It doesn't has to be a content.
So you call:
Human humanOne = new Human(); //Using no-argument constructor
Human humanTwo = new Human(25); //Using constructor with int to set age
When you create a constructor in the class, it will no longer use the default constructor. In your code, you've created a public Human(int) constructor, so there is no default constructor. Because of that, you cannot create human object like this:
Human a = new Human();
To do that, you have to manually implement a no-argument Human constructor.
Here is a solution:
class Human{
String name;
int age;
//default constructor
public Human (){
}
//paramete constructor
public Human(int a){
this.age=a;
}
void speak(){
System.out.println("My name is: " + this.name);
}
int calculateYearsToRetirement(){
int yearsLeft = 65 - age;
return yearsLeft;
}
int getAge(){
return this.age;
}
String getName(){
return this.name;
}
}
Here's the working code :
Create a class GettersAndReturnValue and add this. You need a empty constructor.
class Human{
// declared instance variables
String name;
int age;
// instance method
void speak(){
System.out.println("My name is: " + name);
}
int calculateYearsToRetirement(){
int yearsLeft = 65 - age;
return yearsLeft;
}
int getAge(){
return age;
}
String getName(){
return name;
}
// so when I create an instance, i can't have constructor?
// error here
Human(int age){
this.age = age;
}
public Human() {
// TODO Auto-generated constructor stub
}
}
public class GettersAndReturnValue {
public static void main(String[] args) {
// error here because I created a constructor Human(int a)
Human human1 = new Human();
human1.name = "Joe";
human1.age = 25;
human1.speak();
int years = human1.calculateYearsToRetirement();
System.out.println("Years till retirements " + years);
int age = human1.getAge();
System.out.println(age);
}
}
Output :
My name is: Joe
Years till retirements 40
25

how to call superclass parameterized constructor by subclass?

Why i am getting error in the starting of Employee constructor that cannot find symbol
constuctor Person?
class Person {
String name = "noname";
Person(String nm) {
name = nm;
}
}
class Employee extends Person {
String empID = "0000";
Employee(String eid) {// error
empID = eid;
}
}
public class EmployeeTest {
public static void main(String args[]) {
Employee e1 = new Employee("4321");
System.out.println(e1.empID);
}
}
You need to call
super(name);
as the first statement of the constuctor Employee as the compiler will otherwise implicitly call the no-argument constructor for Person which doesnt exist
where name is an added argument to Employee
Employee(String eid, String name) {
super(name);
empID = eid;
}
Take a look at example 8.2-1 from the JLS which shows how a similar example fails in the absence of an explicit super method call.
When you create an employee, you'll need to specify both a name and an employee id - since every employee is a person, and every person needs a name. The constructor for Employee should probably look like this.
public Employee(String eid, String name) {
super(name);
empID=eid;
}
The super line specifies how to call the superclass's constructor. It needs to be in there because there's no constructor for the superclass without parameters. A superclass constructor must be called, there's only one available constructor, and that constructor needs the name argument to be specified.
You should do something like this to get your program to work:
class Person {
String name = "noname";
Person(String name) {
this.name = name;
}
}
class Employee extends Person {
String empID = "0000";
Employee(String empID , String name) {
super(name);
this.empID = empID;
}
}
public class EmployeeTest {
public static void main(String args[]) {
Employee e1 = new Employee("4321" , "Ramesh");
System.out.println(e1.empID);
System.out.println(e1.name);
}
}
I have a couple of points to add.
It is always a good habit to make your data member private. If you want to access those members outside the class, use getters and setters. ( getName(), setName() etc. )
Your constructors ( Person() and Employee() ) HAVE to be defined if you want to creating an object without using parameterized constructor. NO default contstructor will be provided for you if you want to instantiate using a non-parameterized constructor. So do THIS whenever you are using a parameterized constructor as a good habit:
class Person {
private String name = "noname";
Person() {}
Person(String name) {
this.name = name;
}
public String getName() {
return this.name;
}
public void setName(String name) {
this.name = name;
}
}
class Employee extends Person {
private String empID = "0000";
Employee() {}
Employee(String empID,String name) {
this.empID = empID;
}
public String getEmpID() {
return this.empID;
}
public void setName(String empID) {
this.empID = empID;
}
}

Categories