'3 subclass and 1 main class inheritance, but shows null in output in java?

I'm starting to get into coding. My formats are bad, but I wanna see first if my idea for the program works then correct it later on. This is program consists of the main class (Employee), then two subclasses that inherit from the main class (Part-Time and Full-Time employees) The code works but I encountered null in my employee's name output in this code or maybe I missed something. Any help, correction, or advice would be great! Thank you

Main Class

class Employee {
    public String Name;
    
    public void setName(String Name) 
    {
        this.Name = Name;
    }
    
    public String getName() 
    {
        return Name;
    }
    public void emp() 
    {        
    Scanner scan = new Scanner(System.in);
        System.out.println("Enter Name: ");
            Name = scan.nextLine();
    }
}

Subclass FullTimeEmployee

class FullTimeEmployee extends Employee {
    private double monthlySalary;
    Scanner scan = new Scanner(System.in);
    public void setMonthSalary(double monthlySalary) {
        this.monthlySalary = monthlySalary;
    }
    
    public double getMonthlySalary() {
        return monthlySalary;
    }
    
    @Override
    public void emp() {
    System.out.println("Enter monthly salary: ");
    monthlySalary = scan.nextDouble();
    System.out.println("Name: " + getName());
    System.out.println();
    System.out.println("Monthly Salary: " + monthlySalary);
    }
}

subclass PartTimeEmployee

public class PartTimeEmployee extends Employee {
    Scanner scan = new Scanner(System.in);
    private double ratePerHour;
    private int hoursWorked;
    private double wage;
    
    
    public void setWage(double wage) {
        this.wage = wage;
    }
    
    public double getWage() {
        return wage;
        
    }
    
    @Override
    public void emp() {
    System.out.println("Enter rate per hour and no of hours worked separated by space: ");
    ratePerHour = scan.nextDouble();
    hoursWorked = scan.nextInt();
    System.out.println("Name: " + getName());
    wage = ratePerHour * hoursWorked;
    System.out.println("Wage: " + wage);
    
    }
}

RunEmployee

public class RunEmployee {


    public static void main(String[] args) 
    {
        Scanner scan = new Scanner(System.in);
        Employee emp1 = new Employee();
        FullTimeEmployee fte = new FullTimeEmployee();
        PartTimeEmployee pte = new PartTimeEmployee();
       
        emp1.emp();
        System.out.println("Press F for Full Time or P for Part Time: ");
        char select = scan.nextLine().charAt(0);
        if(select == 'F') {
            fte.emp();
        } else if (select =='P') {
            pte.emp();
        }
    }
}

OUTPUT OF BOTH

Enter monthly salary: 
500
Name: null


Solution 1:[1]

You only set name in the Employee parent class in the emp() method here:

public void emp() {        
    Scanner scan = new Scanner(System.in);
    System.out.println("Enter Name: ");
    Name = scan.nextLine();  // here!
}

And yes, you give your child classes the same method and override and call it, but you never call the parent's version of the method, the super.emp() method, and so the name field never gets set.

A solution would be to call the super.emp() in your overrides, but this isn't good as it breaks the "single responsibility principle". And Employee should be responsible for Employee data and behaviors, but shouldn't be also responsible for handling a Scanner object and getting direct input from the user. Also, there are potential dangers from creating multiple Scanner objects based on System.in.

Much better, get all I/O, all use of Scanner, out of the Employee class and its children. The I/O should be in the main method (for this code) and instead, set name in the Employee constructor, and by calling the super constructor in the child classes, or by directly calling .setName(...) on any instances created.

e.g.,

class Employee {
    public String name;
    
    public Employee(String name) {
        this.name = name;
    }
    
    public Employee() {
        this(null);
    }
    
    public void setName(String Name) {
        this.Name = Name;
    }
    
    public String getName() {
        return Name;
    }
    
    
    // get rid of this
    /* 
    public void emp()  {        
    Scanner scan = new Scanner(System.in);
        System.out.println("Enter Name: ");
            Name = scan.nextLine();
    }
    */
}
public class FullTimeEmployee extends Employee {
    private double monthlySalary;
    // Scanner scan = new Scanner(System.in); // *** get rid of this!
    
    public FullTimeEmployee(String name) {
        super(name);
    }
    
    public FullTimeEmployee() {
        super();
    }
    
    public void setMonthSalary(double monthlySalary) {
        this.monthlySalary = monthlySalary;
    }
    
    public double getMonthlySalary() {
        return monthlySalary;
    }
    
    /*    // get rid of this!
    @Override
    public void emp() {
    System.out.println("Enter monthly salary: ");
    monthlySalary = scan.nextDouble();
    System.out.println("Name: " + getName());
    System.out.println();
    System.out.println("Monthly Salary: " + monthlySalary);
    }
    */
}

and then again, put all Scanner code in the main method.


Regarding variable public String Name;

As an aside, you will want to learn and use Java naming conventions. Variable names should all begin with a lower letter while class names with an upper case letter. Learning this and following this will allow us to better understand your code, and would allow you to better understand the code of others.

Also, avoid using public fields unless absolutely necessary. Better to make this field protected, or even better yet, make it private.

Sources

This article follows the attribution requirements of Stack Overflow and is licensed under CC BY-SA 3.0.

Source: Stack Overflow

Solution Source
Solution 1