trying to call superclass method in subclass - java

Probably a pretty noob question, but I cant figure it out. I have a class Person to store a name that is input from the keyboard
public class Person {
private String firstName;
private String lastName;
public Person()
{
firstName = "";
lastName = "";
}
public Person(String first, String last)
{
setName(first, last);
}
public String toString()
{
return(firstName + " " + lastName);
}
public void setName(String first, String last)
{
firstName = first;
lastName = last;
}
public String getFirstName()
{
return firstName;
}
public String getLastName()
{
return lastName;
}
}
I am trying to call the toString method in a subclass called Patient
public class Patient extends Person {
private int patientID, patientAge;
public Patient()
{
patientID = 0; //for a different part of the class that works
patientAge = 0;
}
#Override
public String toString()
{
return ("Patient Name: "+super.toString());
}
}
I cannot get it to output the name in main when I call the toString method from the Patient class, but when I tested it, it output the name when I call the toString method from the Person class.
The method call in main looks like Patient pnt = new Patient(); System.out.print(Pnt.toString());
it prints out in the console "Patient Name: ". Any feedback on what I am doing wrong or ideas on how to get it to work

Here:
public Person()
{
firstName = "";
lastName = "";
}
Your subclass is missing a reasonable call to a super class constructor. So when you instantiate your Patient objects, the above constructor is used, and all patients end up with "" as first and last name!
When you create a Patient, then a patient should have a name, too! But your constructor in Patient only sets the Patient related fields. And implicitly, the default super constructor is called. Therefore the Person fields are all set to be empty strings!
A much better approach would look like this:
class Person {
private final String firstName;
... lastName
public Person(String firstName, String lastName) {
this.firstName = firstName;
...
and then
class Patient extends Person {
private final int patientID;
public Patient(int patientID, String firstName, String lastName) {
super(firstName, lastName);
this.patientID = patientID;
)
Why is that better: names and IDs don't change (normally). There is no point in having getters for them. You create your object once, and then that data is fixed! There is also no point in having that default constructor in Person. A person with empty names doesn't make sense. Thus: don't create a class that allows you to create "invalid" objects. Your classes model reality. There are no real people without names!
And one other hint: use #Override when overriding methods, so that the compiler can tell you when you get something wrong!

if the problem is to output the name in main when you call the toString method from the Patient class, I think the code bellow will help you.
have you tried to construct the Patient object like this?
public static void main(String[] args) {
Patient p = new Patient();
System.out.println(p.toString());
}

Actually I do not see problem in your code.
Person person = new Person();
person.setName("aa", "bb");
System.out.println(person); // aa bb
Patient patient = new Patient();
patient.setName("cc", "dd");
System.out.println(patient); // Patient Name: cc dd
I think that you set name wrong pr use not correct reference. Check it.

You don't have any constructor for your PATIENT subclass. You don't set any firstName or lastName to any patient.
To keep familiar constructor as you used in your parent class, tru to use:
public Patient() {
super("default_firstName", "default_lastName");
this.patientID = 0;
this.patientAge = 0;
}
public Patient(String firstName, String lastName, int patientAge) {
super(firstName, lastName);
this.patientID = 0; //can be implemented some method for automatically setting numbers
this.patientAge = patientAge;
}
This way you always get firstName and lastName even if constructor will be called empty.
According to you toString method, it's correct and it call super class method:
#Override
public String toString()
{
return("Patient name is "+super.toString());
}
But notice that you return STRING value so to make it visible on the screen remember to use:
System.out.println(patient.toString());
Then it will be visible :)

I have added some comments and code in your Person class that should fix your issues.
public class Person {
private String firstName; //store the first name
private String lastName; //sore the last name
//initialize firstName and lastName to an empty string
public Person() {
firstName = "";
lastName = "";
}
//set firstname and lastname according to the parameters.
public Person(String first, String last) {
//setName(first, last); remove this crap.
// Use the contructor properly when initialize your person object. Like this:
this.firstName = first;
this.lastName = last;
}
//method to output the first name and last name
#Override
public String toString() {
return (firstName + " " + lastName);
}
//method to set firstName and lastName according to the paramters
public void setName(String first, String last) {
//
firstName = first;
lastName = last;
}
}

Related

Accessing private instance fields of parent class from subclass.. but it works?

I have a parent class that has 2 private instance fields but my child class which has no instance fields 'magically' creates 2 instance fields.
public class Parent
{
private String firstName;
public String lastName;
private int age;
public Parent()
{
System.out.println("No-Parameter Constructor");
}
public Parent(String firstName, String lastName, int age)
{
this.firstName = firstName;
this.lastName = lastName;
this.age = age;
}
public String toString()
{
return "firstName: " + firstName + " lastName: " + lastName + " age: " + age;
}
public String getFN()
{
return firstName;
}
}
public class Student extends Parent
{
public Student(String firstName, String lastName, int age)
{
super(firstName, lastName, age);
}
public static void main(String[] args)
{
Parent p = new Parent("Logi", "Tech", 42);
Student s = new Student("Logi", "Camera", 21);
System.out.println(p);
System.out.println(s);
System.out.println(p);
System.out.println(p.getFN());
}
}
Output:
firstName: Logi lastName: Tech age: 42
firstName: LogiStudent lastName: Camera age: 21
firstName: Logi lastName: Tech age: 42
LogiStudent
You are not accessing private fields from the Student class. Just look at your code - nowhere in the body of class Student extends Parent {} do you refer to those fields in any way.
class Student extends Parent is java-ese for: "Let's define this new concept called Student. Begin by taking absolutely every single last thing Parent has, and then bolt, on top of all that, a few more things".
In other words, if Parent has the field 'age, then so does Student.
accessibility is almost entirely unrelated to this notion; accessibility (private) is about which code (NOT which instance!!) is allowed to directly interact with things. Given that the age field is private, whilst every instance of Student has that field, the code located in Student.java cannot touch that field directly. It is of course free to invoke a method that its superclass does allow access to (such as the toString method which is public) and then observe as IT touches those fields. That's not 'direct access', that's indirect, and that is fine.
Similarly, Student can invoke getFN() anywhere it wants, and thus get the first name. It cannot, however, set the firstname, unless Parent decides to add a void setFirstName(String fn) { this.firstName = fn; } method, of course.

Unable to display object array using get(index)

I am trying to display the different objects in an ArrayList. In my project context, one student is one object.
I used an ArrayList to store all the different student objects and I am having problems reading the ArrayList.
<%
String student_name = request.getParameter("studentName");
ArrayList<Object[]> studentList = new ArrayList<Object[]>();
if(student_name != null && student_name.length() > 0) {
PreparedStatement preparedStatement = con.prepareStatement("Select * from users where firstname LIKE ? ");
preparedStatement.setString(1, "%" +student_name+ "%");
ResultSet resultSet = preparedStatement.executeQuery();
while (resultSet.next()) {
String first_name = resultSet.getString("firstname");
String last_name = resultSet.getString("lastname");
String email = resultSet.getString("email");
Object[] student = {first_name,last_name,email};
studentList.add(student);
session.setAttribute("studentObject",studentList);
//System.out.println("First Name: " + first_name + "," + "Last Name: " + last_name);
System.out.println(studentList.get(0));
}
When I try to display (studentList.get(0)), all I see is "[Ljava.lang.String;#XXXX"
How do i get it to display the different student objects based on the index ?
At first, It will be more idiomatic in Java to define your own class Student. Write an extractor to that class, define toString method and it will be great.
Java requires you to define toString method to any type of object that will be printed. So, you have to define toString for your Student class.
But you are using an array. Java doesn't have toString method defined for Arrays. So I would propose you to do something like this. (I'm a bit on rush so code may contain some mistakes:
// At first it could be better to define a structure
// that represents a student
// class must be defined in separate file like Student.java
// Student.java
public class Student {
// constructor for the Student object
public Student(final String firstName,
final String lastName,
final String email) {
this.firstName = firstName;
this.lastName = lastName;
this.email = email;
}
private String firstName;
private String lastName;
private String email;
#override String toString() {
return firstName + " " + lastName + " " + email;
}
// getters
public String getFirstName() { return firstName; }
public String getLastName() { return lastName; }
public String getEmail() { return email; }
// setters
public void setFirstName(final String firstName) {
this.firstName = firstName;
}
public void setLastName(final String lastName) {
this.lastName = lastName;
}
public void setEmail(final String email) {
this.email = email;
}
} // end of Student.java file
///////////////////////////////////////////
final ArrayList<Student> studentList = new ArrayList<Student>();
.... // your code
ResultSet resultSet = preparedStatement.executeQuery();
while (resultSet.next()) {
// creating a new student with new keyword
final Student currentStudent = new Student(
resultSet.getString("firstname"),
resultSet.getString("lastname"),
resultSet.getString("email")
)
// you are adding a student object to the list
studentList.add(currentStudent);
session.setAttribute("studentObject",studentList);
// that should work
// toString method will be called implicitly
System.out.println(studentList.get(0));
}
// So you will have a list of students
// that will be accessable in the following manner:
studentList.get(0).getFirstName;
studentList.get(1).setFirstName("New name");
If you want a different behaviour you may call those fields directly, or modify
the behavior of toString method
Java also assumes that you're using camelCase notation, you may find in in the style guide.
Hope it helps.
Try java.util.Arrays class:
System.out.println(Arrays.toString(studentList.get(0)));
Currently you are printing out the Object[] which is not exactly human readable. I would suggest creating a new class called Student. Then have three member variables firstName, lastName, and email. Also create a toString() method for this new class. Then you can have an ArrayList of Students. This should simplify everything for you.
You have at least two options:
Implement an object corresponding to Object[] student:
In this class you may override Object's toString(), and implement it as to wish to present the data.
NOTE: this is very relevant to you because when printing studentList.get(0) you actually print call Object's default toString() which returns the reference to the object.
For more information regarding default Object.toString() here.
The simplestway is to use Arrays.toString():
System.out.println(Arrays.toString(studentList.get(0)));
It looks like you're not trying to display a String as you expect, you're trying to display an array of Objects.
You could try : System.out.println(studentList.get(0)[0]);
You'll have an idea

Setters, why won't this work?

I've been toying for hours, changing static, private, public etcetera :) But it still won't work. If I change static at one place, I get an error at another place etc.
I have a class called person. I've used NON-static Setters because the Person() constructor is also non-static.
public class Person {
private String name;
private String lastname;
private String nickname;
Person() {
this.name = "";
this.lastname = "";
this.nickname = "";
}
public void setName(String name) {
this.name = name;
}
public void setLastname(String lastname) {
this.lastname = lastname;
}
public void setNickname(String nickname) {
this.nickname = nickname;
}
}
Then I have a file with my main method, and different methods for interacting with the user.This method is also static because it calls that methods that take the userInput which is using the Scanner class.
public class Interaction {
public static void takeName() {
String name;
String lastname;
String nickname;
System.out.println("What is your firstname:");
name = userInput(); // calls method with Scanner class
System.out.println("What is your lastname:");
lastname = userInput(); // calls method with Scanner class
System.out.println("What is your nickname:");
nickname = userInput();
person.setName(name);
person.setLastname(lastname);
person.setNickname(nickname);
}
//editor: missing closing bracket
What I've tried:
I've tried to dat Person.person.setname(name);
Declare the String in the public class Interaction, and then pass the String using this.name and call the method from the public class Interaction
tried to change static, private etc. etc.
Delete the constructor class Person() in Person class.
What am I missing here?
EDIT: I'VE ADDED SOME MORE INFO as you requested :)
My new Person object will be declared if it passes an if statement.
IF there is a place available then a new person will be created and added to this place.
public class Theater {
void reservationSystem () {
if (availability > 0) {
for (int i = 0; i < freespaces.length; i++) {
if (freespaces[i].person == null) {
freespaces[i].person = new Person();
break;
}
}
} else {
System.out.println("No tickets for you today :) ");
}
}
//editor: missing closing bracket
So my way of thinking is:
I fill a constructor with the data from the Userinput() using the Scanner class;
and THEN I create the new Person object so it has that data!
When I create a new Person in the reservation system, then the data in the constructor will be filled with data AGAIN but now with new data :)
If you need any more information please let me know :)
The first thing to note is that your Person constructor is a little useless, you can rewrite Person as such:
public class Person {
private String name = "";
private String lastname = "";
private String nickname = "";
public void setName(String name) {
this.name = name;
}
public void setLastname(String lastname) {
this.lastname = lastname;
}
public void setNickname(String nickname) {
this.nickname = nickname;
}
}
Now onto your Interaction class. This needs to by public rather than Public but I assume that's a typo.
You need to have an instance of Person to call your setters on as they are instance methods. You need to somewhere call new Person().
The easiest way of writing your takeName() method is by creating a Person in the method and returning the instance:
public class Interaction {
public static Person takeName() {
final Person person = new Person();
System.out.println("What is your firstname:");
person.setName(userInput());
System.out.println("What is your lastname:");
person.setLastname(userInput());
System.out.println("What is your nickname:");
person.setNickname(userInput());
return person;
}
}
Your 'takeName()` function should update a single instance of the Person class.
One approach is to create the Person externally and pass it to the function:
Public class Interaction {
public static void takeName(Person person) {
String name;
String lastname;
String nickname;
System.out.println("What is your firstname:");
name = userInput(); // calls method with Scanner class
System.out.println("What is your lastname:");
lastname = userInput(); // calls method with Scanner class
System.out.println("What is your nickname:");
nickname = userInput();
person.setName(name);
person.setLastname(lastname);
person.setNickname(nickname);
}
}
But I think it would be more intuitive to create the person instance inside the function and return it:
Public class Interaction {
public static Person takeName() {
String name;
String lastname;
String nickname;
Person person = new Person();
System.out.println("What is your firstname:");
name = userInput(); // calls method with Scanner class
System.out.println("What is your lastname:");
lastname = userInput(); // calls method with Scanner class
System.out.println("What is your nickname:");
nickname = userInput();
person.setName(name);
person.setLastname(lastname);
person.setNickname(nickname);
return person;
}
}
Because this is not valid syntax: Person.person.setname(name);
What this would mean in this context is:
get class named Person
get static field of Person class named person
find and invoke instance methid setname with argument name
But your Person class - appropriately - does not have a static field named person...
The root cause of your issues is most likely not being entirely familiar with the concept of classes, instances, and in connection, the meaning of static and instance members and methods...
Static always means the referenced part is connected with the class.
Whereas an instance variable or method (e.g. everything non-static) is connected to the instances of said classes.

Ignore default constructor and use constructor with parameters in Java

I am not very well rounded in Java, which is why I am asking this question that is probably very stupid sounding. Nonetheless, I am trying to figure out how to ignore a class's default construct method, and use a construct method with parameters instead. For example, something like this:
public class Name {
String firstName, lastName;
public Name()
{
String dialog = JOptionPane.showInputDialog("First and Last name: ");
Scanner inName = new Scanner(dialog);
firstName = inName.next();
lastName = inName.nextLine();
}
public Name(String newFirst, String newLast)
{
firstName = newFirst;
lastName = newLast;
}
}
I then have a class called Student which extends name as such:
public class Student extends Name
{
public Student(String firstName, String lastName)
{
firstName = firstName;
lastName = lastName;
}
}
So, the first construct method from Name class prompts the user to enter their name, but say I already know the user's name and have it stored in some variables, how can I create a new Student() object (which is really a name() object) without invoking that first default constructor, and instead invoke it as such:
Student student1 = new Student(firstName, lastName);
I understand why the following line would call the default construct method:
Student student1 = new Student();
But the next following line stil calls the same parameterless construct method, even though I am using parameters:
Student student1 = new Student(firstName, lastName);
What am I doing wrong here?
First : using a Scanner to get an input from the external world in a constructor is a terrible idea.
Second : the constructor in Student calls the constructor in Name that takes no parameters since there is no explicit call to super(). If you want to avoid that :
public Student(String firstName, String lastName)
{
super(firstName, lastName);
}
If you don't explicitly call a super constructor from the subclass, it implicitly calls the super constructor that takes no arguments.
To make it more clear, when you write
public Student(String firstName, String lastName)
{
this.firstName = firstName;
this.lastName = lastName;
}
you are in fact doing :
public Student(String firstName, String lastName)
{
super();
this.firstName = firstName;
this.lastName = lastName;
}

Java, I need help instantiating an object

Hello I'm new to Java. I'm trying to create a object and pass name through it. I don't have a clue what I'm doing wrong?.
public class Employee
{
private String name, number;
private String date;
public Employee()
{
name= "";
number = "";
date = "";
}
public Employee(String name, String number, String date)
{
setName(name);
setNumber(number);
setDate(date);
}
public void setName(String n)
{
name = n;
}
public void setNumber(String n)
{
number = n;
// you can check the format here for correctness
}
public void setDate(String d)
{
date = d;
}
public String getName()
{
return name;
}
public String getNumber()
{
return number;
}
public String getDate()
{
return date;
}
}
import java.util.Scanner;
public class TeamLeadDemo
{
public static void main(String[] args)
{
String name;
// create scanner object
Scanner keyboard = new Scanner(System.in);
// inputting data
System.out.println("Enter Name:");
name = keyboard.nextLine();
// instantiating object, HERE IS THE PROBLEM
Employee thename = new Employee(name);
// outputting data
System.out.println("Employee Name:"+thename.getName());
System.out.println("Employee Details:\n" + thename);
}
}// Function definition
What should i do??
Hey fellow newbie programmer!
Take a look at how you initialize your object:
Employee thename = new Employee(name);
Since you only give it the String name as a parameter, Java cannot initialize your Employee object because it does not have a single argument constructor!
Here are your constructors method signatures:
public Employee()
public Employee(String name, String number, String date)
One takes no arguments, and the other takes 3 arguments.
If you look at the way you initialize it, you only pass 1 argument!
You would need to create a new Constructor that has a single argument in order for your code to work. Or easier yet, you could just pass in "", "" for your number and date string values.
More experienced programmers please do not hesitate to correct my programming semantics if they are wrong. I feel like I'm using words that I do not fully understand.
You need a constructor that receives only the name that you are passing:
public Employee(String name) {
this.name = name;
this.number = "";
this.date = "";
}
Currently you only have one default constructor and one that receives all three properties.
Your Employee class has two constructors: one taking zero arguments and one taking three arguments. Yet you're attempting to construct it with one argument. That wouldn't compile.
There are two possible solutions:
Add another constructor taking one argument.
public Employee(String name) {
this.name = name;
}
Use the constructor taking three arguments and pass null through.
Employee employee = new Employee(name, null, null);
Unrelated to the concrete problem, setting values to empty strings in the default constructor and calling the setters in the second constructors is not a nice practice. In the first, just do nothing, keep them default null. In the second constructor, you should prefer setting the property directly instead of calling the setter.
You need to pass in the number and date to the constructor as well. Try:
Employee thename = new Employee(name, "", "");
Employee thename = new Employee(name);
You have no constructor that takes only one String
If you have some very very strong reasons not to use Employee thename = new Employee(name, "", "");, you may try "varargs"
As :
public class Employee {
String fname="";
String lname="";
public Emp(String... attrs) {
if ( attrs.length > 1 ) {
fname = attrs[0];
lname = attrs[1];
}else if(attrs.length == 1) {
fname = attrs[0];
}
}
public String toString() {
return fname + " " + lname;
}
public static void main(String[] args){
Employee e1 = new Employee ("Test");
Employee e2 = new Employee ("Test" ,"case");
System.out.println(e1);
System.out.println(e2);
}
}
Caution : this is just to answer your question- Think before using in real world situations. Not from design/ best approach perspective. But it is different and caters to your question though ;-)

Categories