Logo Questions Linux Laravel Mysql Ubuntu Git Menu
 

How make toString() method return Super Class private fields also along with its instance fields?

Is there a way to make toString() include private fields of the super class? I tried adding a super.toString(), no use however.

Please see the code below

Employee.java

package test;

public class Employee {

private  String name;
private int id;
private double salary;

public Employee(String name, int id, double salary) {
    super();
    this.name = name;
    this.id = id;
    this.salary = salary;
}

public double getSalary() {
    return salary;
}

@Override
public String toString() {
    return "Employee [name=" + name + ", id=" + id + ", salary=" + salary
            + "]";
}

public static void main(String[] args) {

    Employee e=new Employee("Joe", 14, 5000);
    System.out.println(e);
    Manager m=new Manager("Bill", 23, 5000, 10);
    System.out.println(m);
    System.out.println("Employee Salary is "+e.getSalary()+"\nManager salary is "+m.getSalary());
}
}

Manager.java

package test;

public class Manager extends Employee{

private double bonus;
public Manager(String name, int id, double salary,int bonus) {
    super(name, id, salary);
    this.bonus=bonus;
}

public double getSalary()
{
    double baseSalary=super.getSalary();

    return (baseSalary+baseSalary*(bonus/100));

}

@Override
public String toString() {
    return(this.getClass().getName()+" ["+super.toString().substring((this.getClass().getSuperclass().getName().length()-3
            ), (super.toString().length())-1)+", bonus="+bonus+"]");
    //didn't work
    //super.toString();
    //return "Manager [bonus=" + bonus + "]";
}



}

Output

Employee [name=Joe, id=14, salary=5000.0]
test.Manager [name=Bill, id=23, salary=5000.0, bonus=10.0]
Employee Salary is 5000.0
Manager salary is 5500.0

That was the best i could do , to concatenate super.toString()+' a set of Strings', surely this is messy , is there some other way , even if the language spec does not allow it does eclipse have some facility to do that , NOTE: I used eclipse to generate the toString method , any way by which i can tell eclipse to include the super class fields too,

In other words can i replace this messy code

return(this.getClass().getName()+" ["+super.toString().substring((this.getClass().getSuperclass().getName().length()-3
            ), (super.toString().length())-1)+", bonus="+bonus+"]");

by getting eclipse to automate the process and generate a suitable way to do it?

like image 958
Sainath S.R Avatar asked Nov 26 '14 08:11

Sainath S.R


People also ask

What is the return type of the toString () method in the object class?

The toString() method returns the String representation of the object.

What does a toString () method returns as a string?

toString() − This returns a String object representing the value of this Integer. toString(int i) − This returns a String object representing the specified integer.

How do you call a super class toString method?

In a subclass, toString() can call the superclass toString() method using super. toString() and then add on its own attributes. In the following code, the Person class overrides the Object toString() method and the Student class overrides the Person toString() method. They each add on their attributes.

What is the function of toString () method?

For user-defined Function objects, the toString method returns a string containing the source text segment which was used to define the function. JavaScript calls the toString method automatically when a Function is to be represented as a text value, e.g. when a function is concatenated with a string.


2 Answers

If you create getters and setters in your superclass then you can acces the variables through those methods. Other possibility is to change the visibility from private to protected

first solution looks like this

Employee

public class Employee {

    private String name;
    private int id;
    private double salary;

    public Employee(String name, int id, double salary) {
        super();
        this.name = name;
        this.id = id;
        this.salary = salary;
    }

    public double getSalary() {
        return salary;
    }

    public String getName() {
        return name;
    }

    public void setName(String name) {
        this.name = name;
    }

    public int getId() {
        return id;
    }

    public void setId(int id) {
        this.id = id;
    }

    public void setSalary(double salary) {
        this.salary = salary;
    }

    @Override
    public String toString() {
        return "Employee [name=" + name + ", id=" + id + ", salary=" + salary + "]";
    }
}

Manager

public class Manager extends Employee {

    private double bonus;

    public Manager(String name, int id, double salary, int bonus) {
        super(name, id, salary);
        this.bonus = bonus;
    }

    public double getSalary() {
        double baseSalary = super.getSalary();

        return (baseSalary + baseSalary * (bonus / 100));

    }

    @Override
    public String toString() {
        return "Manager [name=" + getName() + ", id=" + getId() + ", salary=" + getSalary() + ", bonus=" + bonus + "]";
    }

}

Second one (using protected)

Employee

public class Employee {

    protected String name;
    protected int id;
    protected double salary;

    public Employee(String name, int id, double salary) {
        super();
        this.name = name;
        this.id = id;
        this.salary = salary;
    }

    public double getSalary() {
        return salary;
    }



    @Override
    public String toString() {
        return "Employee [name=" + name + ", id=" + id + ", salary=" + salary + "]";
    }
}

Manager

public class Manager extends Employee {

    protected double bonus;

    public Manager(String name, int id, double salary, int bonus) {
        super(name, id, salary);
        this.bonus = bonus;
    }

    public double getSalary() {
        double baseSalary = super.getSalary();

        return (baseSalary + baseSalary * (bonus / 100));

    }

    @Override
    public String toString() {
        return "Manager [name=" + name + ", id=" + id + ", salary=" + salary + ", bonus=" + bonus + "]";
    }

}

Personally i'd use the getter/setter method but it's up to you.

EDIT: Additonal to eclipse generation of toString() in eclipse. You can't seem to generate it with getters and setter (just had a quick look, you can see some documentation here. What I did figure out is how you can edit the Code Template used when generating the toString() so it includes the toString() from the superclass.

When you enter the generate toString() dialog there is a field 'String Format' with <Default Template> next to it. when you click the edit button you can create a new Code Template. This template automatically holds the <Default Template> and should look something like this:

${object.className} [${member.name()}=${member.value}, ${otherMembers}]

only thing you'll have to add is the following at the end

[super: ${object.superToString}]

This way it'll display the toString() form the superclass

like image 187
Liam de Haas Avatar answered Nov 07 '22 01:11

Liam de Haas


You can let eclipse generate it, however it would not look like you want it.

Eclipse generate toString() dialog

which creates this code:

public String toString() {
    return "Manager [bonus=" + bonus + ", toString()=" + super.toString() + "]";
}

which would print this:

Manager [bonus=10.0, toString()=Employee [name=Bill, id=23, salary=5000.0]]

That's the most you can make eclipse generate for you.

You can clean it up a little so it would look like this

public String toString() {
    return "Manager [bonus=" + bonus +  "] is a " + super.toString();
}

which would print

Manager [bonus=10.0] is a Employee [name=Bill, id=23, salary=5000.0]


However, your custom solution works as well. So why not use it?

You can clean it up a little like this:

@Override
public String toString() {
    return "Manager [" + superFieldsFromToString() + ", bonus=" + bonus + "]";
}

private String superFieldsFromToString() {
    String superToString = super.toString();
    int superClassNameLength = getClass().getSuperclass().getSimpleName().length();
    int fieldStartIdx = superClassNameLength + 2; // + 2 removes " ["
    int fieldEndIdx = superToString.length() - 1; // - 1 removes "]"
    return superToString.substring(fieldStartIdx , fieldEndIdx);
}

which outputs

Manager [name=Bill, id=23, salary=5000.0, bonus=10.0]

The only other options, as others have mentioned, are to use reflection to access the private fields, make the fields protected or create public getters.

I would not advice to do any of this, as your class design should not be defined by debug output.

like image 11
Timo Türschmann Avatar answered Nov 07 '22 00:11

Timo Türschmann