如何使 toString() 方法同时返回超类私有字段及其实例字段?

有没有办法让包括私人领域的超级?我尝试添加一个,但是没有用。toString()classsuper.toString()

请参阅下面的代码

员工.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());
}
}

经理.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 + "]";
}



}

输出

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

这是我能做的最好的,连接+'一组字符串',当然这很混乱,还有其他方法,即使语言规范不允许它确实eclipse有一些工具可以做到这一点,注意:我使用eclipse来生成toString方法,任何我可以告诉eclipse包括超类字段的方法,super.toString()

换句话说,我可以替换这个混乱的代码吗?

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

通过获取 eclipse 来自动化该过程并生成合适的方法来执行此操作?


答案 1

如果在超类中创建 getter 和 setter,则可以通过这些方法访问变量。其他可能性是将可见性从私有更改为受保护

第一个解决方案看起来像这样

员工

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 + "]";
    }
}

经理

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 + "]";
    }

}

第二个(使用受保护)

员工

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 + "]";
    }
}

经理

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 + "]";
    }

}

就个人而言,我会使用getter/setter方法,但这取决于你。

编辑:在日食中附加到日食生成。您似乎无法使用 getter 和 setter 生成它(只需快速浏览一下,您可以在此处查看一些文档。我确实弄清楚了如何编辑生成时使用的代码模板,使其包含来自超类的。toString()toString()toString()

当您进入生成 toString() 对话框时,旁边有一个字段“字符串格式”。单击编辑按钮时,可以创建新的代码模板。此模板会自动保存 ,并应如下所示:<Default Template><Default Template>

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

您唯一需要添加的是末尾的以下内容

[super: ${object.superToString}]

这样,它将显示超类的形式toString()


答案 2

你可以让日食生成它,但是它看起来并不像你想要的。

Eclipse generate toString() dialog

这将创建以下代码:

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

这将打印以下内容:

经理 [奖金=10.0,toString()=员工 [姓名=账单,id=23,薪水=5000.0]]

这是你能让日食为你生成的最多的东西。

你可以稍微清理一下,这样它就会看起来像这样

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

这将打印

经理 [奖金=10.0] 是员工 [姓名=账单,id=23,工资=5000.0]


但是,您的自定义解决方案也同样有效。那么为什么不使用它呢?

你可以像这样清理它:

@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);
}

哪些输出

经理 [姓名=账单,id=23,薪水=5000.0,奖金=10.0]

正如其他人所提到的,唯一的其他选项是使用反射来访问私有字段,使字段受到保护或创建公共getter。

我不建议这样做,因为你的类设计不应该由调试输出来定义。