toString method for an overloaded constructor - java

I'm trying to find out how to make separate toString methods based on an overloaded constructor. Take the below code for example:
public class Employee {
private double salary;
private String name;
public Employee(String name) {
this.name = name;
}
public Employee(String name, int salary) {
this.name = name;
this.salary = salary;
}
}
Now, I would like to implement a toString method that is dependent on the object created and output the corresponding values.(i.e. one that outputs just name, the other that outputs name and salary) Do I need only one toString method and need to add an if-else statement?
Sorry if this is a silly question, I'm just learning the ropes of Java.

You can only have one toString(), but you can determine the object's "state" and put together the string accordingly. For instance, you can have a salary of -1 indicate that the first constructor was called. Therefore, your toString() would look like:
#Override
public String toString() {
if (salary < 0) {
...
} else {
...
}
}
Don't forget to set salary to -1 in the first constructor.

Well what you are doing here is just instantiating constructors, which has nothing to do with any methods. Constructors just help you initialize and sort of provide context to variables that you will be working with.
If as you said, printing or output-ing the salary and name, you would have to create methods like:
public String printName(){
return name;
}
public String printAll(){
return name + "" + String.valueOf(salary);
}

First, make your salary a negative double (hopefully no one pays to work)... then, default your name field to null. Finally, check for nulls (or negative) in toString(). So, something like this -
private double salary = -1;
private String name = null;
public Employee(String name) {
this.name = name;
}
public Employee(String name, double salary) { // <-- salary isn't an int.
this.name = name;
this.salary = salary;
}
public String toString() {
StringBuilder sb = new StringBuilder();
if (name != null) {
sb.append(name);
if (salary > 0) { // = only if both are valid.
sb.append(" = ");
}
}
if (salary > 0) {
sb.append(salary);
}
return sb.toString();
}

Related

If I create an array of the parental class, how do I access a method from the sub class through the array object?

I have a program I am working with to help me practice my coding skills. The program has the following scenario: there is a classroom of 20 students, where the record is taken of the students' names, surnames, and age. Half of these students take part in the school's athletics. Here, record is kept of their races that they have done and the ones they've won.
In this program, I have three classes:
runStudents - class with main method
Students (String name, String surname, int age) - parental class
AthleticStudents (String name, String surname, int age, int races, int victories) - sub class
The user should be able to add another race (and win) to the object. As seen by the code provided, an Array is created to store the 20 Students objects. I have to be able to access a method to alter the object in the array, but this method is not in the parental class (the class the objects are created from.
public class Students
{
private String name;
private String surname;
private int age;
public Students()
{
}
public Students(String name, String surname, int age)
{
this.name = name;
this.surname = surname;
this.age = age;
}
public String getName()
{
return this.name;
}
public String getSurname()
{
return this.surname;
}
public double getAge()
{
return this.age;
}
public void setName(String name)
{
this.name = name;
}
public void setSurname(String surname)
{
this.surname = surname;
}
public void setAge(int age)
{
this.age = age;
}
public String toString()
{
return String.format("name\t\t: %s\nsurname\t\t: %s\nage\t\t: %s",
this.name, this.surname, this.age);
}
}
public class AthleticStudents extends Students
{
private int races;
private int victories;
public AthleticStudents()
{
}
public AthleticStudents(String name, String surname, int age, int
races, int victories)
{
super(name, surname, age);
this.races = races;
this.victories = victories;
}
public int getRaces()
{
return this.races;
}
public int getVictories()
{
return this.victories;
}
public void setRaces(int races)
{
this.races = races;
}
public void setVictories(int victories)
{
this.victories = victories;
}
public void anotherRace()
{
this.races = this.races + 1;
}
public void anotherWin()
{
this.victories = this.victories + 1;
}
public String toString()
{
return super.toString() + String.format("\nnumber of races\t:
%s\nnumber of wins\t: %s", this.races, this.victories);
}
}
public class runStudents
{
public static void main(String[]args)
{
Students[] myStudents = new Students[20];
myStudents[0] = new Students("John", "Richards", 15);
myStudents[1] = new AthleticStudents("Eva", "Grey", 14, 3, 1);
myStudents[2] = new Students("Lena", "Brie", 15);
for (int i = 0; i < 3; i++)
System.out.println(myStudents[i].toString() + "\n\n");
}
}
I want to be able to do the following:
AthleticStudents[1].anotherRace();
but cannot do so as the array object is derived from the parental class, and I declared the method in the sub class. How can I link the two?
I assume that you create an array of the parent class instances. Just cast the instance this way (you better check whether the element is the instance of a subclass):
if (AthleticStudents[1] instanceof AthleticStudents)
((AthleticStudents) AthleticStudents[1]).anotherRace();
I'm not sure if this is exactly what you're looking for but it worked well for me. Instead of trying to access AthleticStudents method anotherRace() like that, try this in your main method.
Students[] myStudents = new Students[20];
myStudents[0] = new Students("John", "Richards", 15);
myStudents[1] = new AthleticStudents("Eva", "Grey", 14, 3, 1);
myStudents[2] = new Students("Lena", "Brie", 15);
AthleticStudents addRace= (AthleticStudents)myStudents[1];
addRace.anotherRace(); //This will increment Eva's race count to 4
for (int i = 0; i < 3; i++)
System.out.println(myStudents[i].toString() + "\n\n");
All I did was cast the element into an object AthleticStudents named 'addRace'. By casting myStudents[1] to this new object you are able to access all of AthleticStudents methods.
I just saw the other answer posted which works just as well!
Hope this helps!
I’m not sure that i understand your question, because you are a bit inconsistent with your capitalization. runStudents is a class, while AthleticStudents is both a class and an array. But i’ll try.
IF i did understand your question, you have an array Student[] studentArray. Some Student objects in studentArray are AthleticStudents, others are not. You have a specific AthleticStudent eva which is in studentArray[] having let’s say index 1, and you want to add to her anotherRace(). Your call studentArray[1].anotherRace does not compile because the compiler treats that element as a Student and not as a AthleticStudent.
The trick is to cast the element to AthleticStudent. I omit the test of the element of being really an AthleticStudent; you will have to do that test in your code.
((AthleticStudent) studentArray[1]).anotherRace();

I'm having problems with understanding Object Orientation - java

I have been asked to create a class which simply prints "You have been registered".
In the second part, I am to create a test class. The test class should create two student instances (also called objects). Then to print their names and call the registered method of both of them. I keep getting errors saying 'the assignment to variable yearOfBirth has no effect' and in the test class 'The constructor String is undefined'.
Can you help with understanding the errors in my code.
public class Student{
//Attributes
private String name;
private String gender;
private int yearOfBirth;
//Constructors
public Student (String name, String gender, int yearOfBirth){
this.name = name;
this.gender = gender;
this.yearOfBirth = yearOfBirth; // Default age of new student
}
public Student (String name, String gender){
this.name = name;
this.gender = gender;
this.yearOfBirth = 0;
}
//Getters & Setters
public String getName() {
return name; }
public void setName (String name) {
this.name = name;
}
public String getGender () {
return gender;
}
public void setGender (String gender) {
this.gender = gender;
}
public int getYearOfBirth() {
return yearOfBirth;
}
public void setYearOfBirth() {
if(yearOfBirth >= 0 && yearOfBirth <= 100) {
this.yearOfBirth = yearOfBirth;
}else {
System.out.println("Age not valid");
}
}
// Other Methods
public void Registered() {
System.out.println(name + "You have been registered");
}
}
public class StudentTest {
public static void main(String[] args) {
Student student1 =new Student("Kevin Sanches", "male", "1972");
Student student2 = new Student("Cameron Young", "male", "1993");
student1.Registered();
student2.Registered();
System.out.println(student1);
System.out.println(student1);
}
}
There are two issues in your code:
The assignment to variable yearOfBirth has no effect. You are invoking a setter method on a property but you are not passing any value, hence the warning. You should provide a value as a parameter and set that to the corresponding object property.
The constructor problem is that the age parameter is of type int instead when you construct the objects you are passing the age as string.
Your constructor expects two strings and an integer as parameters. You are passing three strings.
Correct way:
Student student1 =new Student("Kevin Sanches", "male", 1972);
Student student2 = new Student("Cameron Young", "male", 1993);
Also, in your method setYearOfBirth you forgot to pass the yearOfBirth as parameter.
public void setYearOfBirth(int yearOfBirth) {
if(yearOfBirth >= 0 && yearOfBirth <= 100) {
this.yearOfBirth = yearOfBirth;
}else {
System.out.println("Age not valid");
}
}
You are trying to send 3 Strings which none of your constructors are ready to take. You have a constructor with 2 Strings and an int, so the correct way of creating the object would be,
Student student1 = new Student("Kevin Sanches", "male", 1972);
Without the double quotes 1972 would be an int.
You are assigning this.yearOfBirth to this.yearOfbirth in the setter. Even though code is just this.yearOfBirth = yearOfBirth; technically both are this.yearOfBirth variables.
This needs to change by accepting the value and assigning it like:
public void setYearOfBirth(int yearOfBirth) {
if(yearOfBirth >= 0 && yearOfBirth <= 100) {
this.yearOfBirth = yearOfBirth;
}else {
System.out.println("Age not valid");
}
}
You are trying to pass a String value to the constructor that accepts int for the yearOfBirth value, change it like:
Student student1 =new Student("Kevin Sanches", "male", 1972);
Student student2 = new Student("Cameron Young", "male", 1993);

How to correctly configure multiple constructors?

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.

How can I search the ArrayList for an item?

I want to search ExArrayList for a specific gpa? I want an answer of true or false if it exists in ArrayList.
public class ExArrayList {
private String Name;
private double GPA;
public ExArrayList(String name, double gpa) {
this.Name = name;
this.GPA = gpa;
}
public void setGPA(double gpa) {
this.GPA = gpa;
}
public double getGPA() {
return GPA;
}
public void setName(String name) {
this.Name = name;
}
public String getName() {
return Name;
}
#Override
public String toString() {
return String.format("%s\t%f", this.Name, this.GPA);
}
}
public class Main {
public static void main(String[] args) {
ArrayList<ExArrayList> psy101 = new ArrayList<>();
psy101.add(new ExArrayList("Bob", 2.9 ));
psy101.add(new ExArrayList("Steve", 3.9 ));
psy101.add(new ExArrayList("Charles", 4.0 ));
System.out.println();
System.out.printf("Student\tGPA\n");
for(ExArrayList s : psy101) {
System.out.printf("%s\n", s);
}
boolean binFound = psy101.contains(2.9); // This is what I am using to search the ArrayList. It's not working.
System.out.println("Does the list contain GPA of 2.9? " + binFound);`
You could steam the list and use a lambda to look for matches:
boolean binFound = psy101.stream().anyMatch(g -> g.getGPA() == 2.9);
You have to do a compare in the for each loop.
if(s.getGPA == 2.9){
binFound = true;
break;
}
Without Java8 Streams:
boolean binFound = false;
for(ExArrayList exArrayList : psy101) {
if(exArrayList.getGPA() == 2.9) {
binFound = true;
break;
}
}
System.out.println(binFound);
With Java8 Streams:
boolean binFound = psy101.stream().map(ExArrayList::getGPA).
anyMatch(gpa -> gpa == 2.9);
System.out.println(binFound);
I did not like any of these answers. People forgot about the precision errors that occur when trying to compare doubles. I know it should not be too bad for GPA purposes because there isn't a lot of precision involved. However, there is the OK way or the right way of doing things.
See this and this for clarification.
The right way of doing what you are planning is with binary search. But, first the list need to be sorted for it to work.
How to sort Objects in Java? You need to know first how to compare their values and there are a couple of ways of doing this. For my example, I will use Comparable. Check this for learning purposes.
Use this import before anything
import java.util.*;
Now, we implement Comparable in your object. It will look like this after the changes:
public class ExArrayList implements Comparable<ExArrayList> {
private String Name;
private double GPA;
public ExArrayList(String name, double gpa) {
this.Name = name;
this.GPA = gpa;
}
public void setGPA(double gpa) {
this.GPA = gpa;
}
public double getGPA() {
return GPA;
}
public void setName(String name) {
this.Name = name;
}
public String getName() {
return Name;
}
#Override
public String toString() {
return String.format("%s\t%f", this.Name, this.GPA);
}
//new stuff needed to compare the objects
public int compareTo(ExArrayList other) {
return Double.compare(this.GPA, other.GPA);
}
}
Now we can sort your list by doing:
Collections.sort(psy101);
After sorting it, we can search the index of the object by doing:
//here we must pass a fake object with the value that we are trying to find
int index = Collections.binarySearch(psy101, new ExArrayList(null, 2.9));
System.out.println(index >= 0 ? "True" : "False");
index contains the position of 2.9 in the list which is 0, if not found it will contain a negative number.

Drive Tester for a Class Issues

I have been putting together a Drive Tester to test a class I have been working on for an assignment, but I have hit a dead end with the tester and I am not sure how to finish it up and remove any errors.
Here is the tester:
public class PersonTester
{
public static void main(String[] args)
{
System.out.println("PersonClassTester");
System.out.println("*****************");
System.out.println("");
Person joeSmith = new Person();
String "smith" = joeSmith.setSurName(); // All these statements with set surname and forname etc are apperantly not statements and require a semi-colon, even though they are there.
String "joe" = joeSmith.setForName();
int 25 = joeSmith.setAge();
double 1.57 = joeSmith.setHeight();
String "male" = joeSmith.setGender();
joeSmith.toString();
joeSmith.format();
}
}
The main issue with this is that the Netbeans client is stating that the setter statements highlighted are not actually statements, and are saying that it needs a semi-colon for each of them despite them actually being there. It is also saying that there are no formal or actual arguments. I know what they are but I'm getting confused on them regardless.
And this is the class I need to run through the tester:
public class Person
{
private String surName;
private String forName;
private int age;
private double height;
private String gender;
#Override
public String toString()
{
return getClass().getName() + "[surName= " + surName + " forName= " + forName + " age= " + age + " height= " + height + " gender " + gender + "]";
}
public void format()
{
System.out.format("%10s%10s%10d%10f%10s", surName, forName, age, height, gender);
}
public String getSurName()
{
return surName;
}
public String getForName()
{
return forName;
}
public int getAge()
{
return age;
}
public double getHeight()
{
return height;
}
public String getGender()
{
return gender;
}
public void setSurName(String surName)
{
this.surName = surName;
}
public void setForName(String forName)
{
this.forName = forName;
}
public void setAge(int age)
{
this.age = age;
}
public void setHeight(double height)
{
this.height = height;
}
public void setGender(String gender)
{
this.gender = gender;
}
}
Any advice on getting the class tester to function properly? Once the tester works the rest of the assignment shouldnt be much of a problem.
Edit: The program compiles, but is unable to print the String statements.
PersonClassTester
*****************
surName forName 25 1.570000 gender
String "smith" = joeSmith.setSurName(); is not correct syntax. It should look like this:
joeSmith.setSurName("smith")
This tells Java to execute the method setSurName() on the object joeSmith, with the given string as an argument.
The same goes for the rest of your assignments in main.
Your setter method looks like:
public void setSurName(String surName)
{
this.surName = surName;
}
Which says your setter is not going to return anything and it expects one parameter which is of String type.
Now here's how you are using your setter method:
String "smith" = joeSmith.setSurName();
So here it means you are expecting a surname from setter which is one part of compiler error that you see. And as stated, it expects a string argument and you are not passing it and that's another part of compiler issue.
So you may want to change it to:
joeSmith.setSurName("smith");//similar changes with other setter method.
Which means, now you are passing string argument and not expecting anything in return by calling this method and hence Compiler would be happy with this.

Categories