0

I have created a Person, class and a Professor class that both use the Builder Pattern to create objects. The Professor class takes a Person object as an argument in its constructor. I am trying to use both classes together, but when I attempt to print out a professor, get the following output: null null (instead of Bob Smith).

Here's what I tried so far:

Person:

public class Person {
    private String firstname;
    private String lastname;
    private int age;
    private String phoneNumber;
    private String emailAddress;
    private char gender;

    public Person(){}

    // builder pattern chosen due to number of instance fields
    public static class PersonBuilder {
        // required parameters
        private final String firstname;
        private final String lastname;

        // optional parameters
        private int age;
        private String phoneNumber;
        private String emailAddress;
        private char gender;

        public PersonBuilder(String firstname, String lastname) {
            this.firstname = firstname;
            this.lastname = lastname;
        }

        public PersonBuilder age(int age) {
            this.age = age;
            return this;
        }
        public PersonBuilder phoneNumber(String phoneNumber) {
            this.phoneNumber = phoneNumber;
            return this;
        }
        public PersonBuilder emailAddress(String emailAddress) {
            this.emailAddress = emailAddress;
            return this;
        }
        public PersonBuilder gender(char gender) {
            this.gender = gender; 
            return this;
        }

        public Person build() {
            return new Person(this);
        }
    }

    // person constructor
    private Person(PersonBuilder builder) {
        this.firstname = builder.firstname;
        this.lastname = builder.lastname;
        this.age = builder.age;
        this.phoneNumber = builder.phoneNumber;
        this.emailAddress = builder.emailAddress;
        this.gender = builder.gender;

    }

    @Override
    public String toString() {
        return this.firstname + " " +  this.lastname;
    }
}

Here's the Professor class:

package com.example.hardcodedloginform;

import java.util.List;

public class Professor extends Person{
    private Person professor;
    private double salary;
    private String courseTaught;
    private List<Student> students;
    private int professorID;


    public static class ProfessorBuilder {
        // required fields
        private Person professor;
        private int professorID;

        // optional fields
        private double salary;
        private String courseTaught;
        private List<Student> students;


        public ProfessorBuilder(Person professor, int professorID) {
            this.professor = professor;
            this.professorID = professorID;
        }



        public ProfessorBuilder salary(double salary) {
            this.salary = salary;
            return this;
        }
        public ProfessorBuilder courseTaught(String courseTaught) {
            this.courseTaught = courseTaught;
            return this;
        }
        public ProfessorBuilder students(List<Student> students) {
            this.students = students; 
            return this;
        }

        public Professor build() {
            return new Professor(this);
        }
    }

    private Professor(ProfessorBuilder builder) {
        this.salary = builder.salary;
        this.courseTaught = builder.courseTaught;
        this.students = builder.students;
    }

    @Override
    public String toString() {
        return "" + super.toString();
    }
}

And here is the Main class where I try to print out a professor object:

public class Main {

    public static void main(String[] args) {
        Person profBobs = new Person.PersonBuilder("Bob", "Smith")
                .age(35)
                .emailAddress("bob.smith@SNHU.edu")
                .gender('M')
                .phoneNumber("818-987-6574")
                .build();
        Professor profBob = new Professor.ProfessorBuilder(profBobs, 12345)
                .courseTaught("MAT101")
                .salary(15230.01)
                .build();
        System.out.println(profBob);
    }

}

I would like the printout in the console to be "Bob Smith", but what I am seeing is: null null. I checked and found that the Person object profBobs is, in fact, created properly and does print out the name "Bob Smith" when I attempt to print it the same way. I don't know why my Professor prints: null null.

  • 1
    Your `Professor` constructor does not initialise the fields of the base class. – Konrad Rudolph Dec 20 '22 at 15:45
  • That fixed it. I had a feeling it was something really simple that I was missing. I never included the professor or professorID fields in the Professor class constructor. I fixed the toString() method too. Thanks! – SapereAude Dec 20 '22 at 15:56

1 Answers1

1

Your Professor constructor fails to initialise any member fields of its base class.

There are multiple ways to solve this. One solution has ProfessorBuilder extend PersonBuilder:

public class Professor extends Person {
    // Remove the `person` field! A professor *is-a* person, it does not *contain* it.
    private double salary;
    private String courseTaught;
    private List<Student> students;
    private int professorID;

    public static class ProfessorBuilder extends Person.PersonBuilder {
        // required fields
        private int professorID;

        // optional fields
        private double salary;
        private String courseTaught;
        private List<Student> students;

        public ProfessorBuilder(Person professor, int professorID) {
            super(professor);
            this.professorID = professorID;
        }

        // …
    }

    private Professor(ProfessorBuilder builder) {
        super(builder);
        this.salary = builder.salary;
        this.courseTaught = builder.courseTaught;
        this.students = builder.students;
    }
}

For this to work you also need to mark the Person constructor as protected rather than private.

Furthermore, your Professor.toString method implementation made no sense: it essentially just called the base class method, so there’s no need to override it. And prepending the empty string does nothing.

Konrad Rudolph
  • 530,221
  • 131
  • 937
  • 1,214