繁体   English   中英

继承超变量

[英]Inheritance super variables

我正在编写一个简单的程序,其中有一个超类Person由子类CustomerEmployee继承(它们继承了变量IDnamesurname )。

public class Person {

    int id;
    String name;
    String surname;

    public Person() {}

    public Person(int i, String n, String s) {
        id = i;
        name = n;
        surname = s;
    }
}
public class Employee extends Person implements Serializable {

    String username;
    String password;
    String date;
    int hpw;
    int recordSold;
    float hourPay;

    public Employee() {}

    public Employee(String u, String n, String s, String p, int i, int h, String d, int rSold, float hPay) {
        username = u;
        super.name = n;
        super.surname = s;
        password = p;
        super.id = i;
        hpw = h;
        date = d;
        recordSold = rSold;
        hourPay = hPay;
    }
}

但是问题出在这里:当我尝试通过主类获取变量IDnamesurname ,它们无法返回(0,null,null)。 为什么是这样? 我的子类中有get-Methods应该返回超级变量,但不是。 感谢您的时间和耐心等待。

public String getName() {
    return super.name;
}

更新:好的,所以我在Employee类构造函数中整理了super(id,name,surname)。 我还删除了员工类中的所有getter和setter,因为它们是从Person超类继承的(如果我错了,请纠正我吗?

人超类:

public class Person {
private int id;
private String name;
private String surname;

public Person () {
}

public Person(int i, String n, String s) {
    this.id = i;
    this.name = n;
    this.surname = s;
}

public void setID(int i) {
    this.id = i;
}
public void setName(String n) {
    this.name = n;
}
public void setSurname(String s) {
    this.surname = s;
}

public int getID() {
    return id;
}
public String getName() {
    return name;
}
public String getSurname() {
    return surname;
}

}

员工子类别:

import java.io.*;
public class Employee extends Person implements Serializable {

protected String username;
protected String password;
protected String date;  
protected int hpw;
protected int recordSold;
protected float hourPay;

public Employee() {
    super();
}

public Employee(int i, String u, String n, String s, String p, int h, String d, int r, float hP) {
    super(i,n,s);
    username = u;
    password = p;
    date = d;
    hpw = h;
    recordSold = r;
    hourPay = hP;
}

public void setUser(String u) {
    username = u;
}

public void setPassword(String p) {
    password = p;
}

public void setHWeek (int h) {
    hpw = h;
}

public void setDate (String d) {
    date = d;
}

public void setRSold (int r) {
    recordSold = r;
}

public void setHPay (float p) {
    hourPay = p;
}

public String getUser() {
    return username;
}

public String getPassword() {
    return password;
}

public int getHWeek() {
    return hpw;
}

public String getDate() {
    return date;
}

public int getRSold() {
    return recordSold;
}

public float getHPay() {
    return hourPay;
}

但是,当我运行主程序时,ID,名称和姓氏变量仍然为空,超类不会返回它们。 我想念什么吗? 谢谢

您的代码应如下所示:

public class Person {

  private int id;
  private String name;
  private String surname;

  public Person (int id, String name, String surname) {
    this.id = id;
    this.name = name;
    this.surname = surname;
  }

  public int getId() {
    return id;
  }

  ... //similarly for getName() and getSurname()
}


public class Employee extends Person {

  private String username;
  private String password;
  private String date; 
  private int hpw;
  private int recordSold;
  private float hourPay;

  public Employee (int id, String name, String surname, String username, String password, String date, int hpw, int recordSold, float hourPay) {
    super(id, name, surname);

    this.username = username;
    ... //similarly for other parameters.
  }
 }

重要的位是super(id, name, surname)

编辑

lionc声称我没有回答这个问题,这是真的。 我这样做是因为原始张贴者似乎不是Java新手,因此可能会问“错误”的问题。 我应该在最初的答复中强调这一点。 鉴于我的答案目前被标记为最好,我相信我做出了正确的决定。

继承仅适用于方法, 不适用于变量。 在子类中实现直接访问超类变量的方法也是不好的做法。 您最好在超类中实现访问方法。 由于继承,这些方法也将在子类中可用。

另一件事是实例变量的可见性。 您正在使用默认可见性,即“程序包范围”。 因此,如果您的子类不在同一包中,则它们将无法访问这些变量。 如果使用“私有”或“受保护”可见性,则访问变量要安全得多。

另一点是您没有正确初始化对象。 调用子类构造函数也必须调用超类构造函数,因为Employee对象依赖于Person对象提供的功能。 对此原理存在更科学的描述:

芭芭拉·利斯科夫(Barbara Liskov)-利斯科夫替代原理

public class Person {

    private int id;
    private String name;
    private String surname;

    public Person() {}

    public Person(int i, String n, String s) {
        id = i;
        name = n;
        surname = s;
    }

    public int getId() {
        return this.id;
    }

    public String getName() {
        return this.name;
    }

    public int getSurname() {
        return this.surname;
    }
}

为超类实例变量添加访问方法,并将可见性设置为私有。

public class Employee extends Person implements Serializable {

    private String username;
    private String password;
    private String date;
    private int hpw;
    private int recordSold;
    private float hourPay;

    public Employee() {}

    public Employee(String u, String n, String s, String p, int i, int h, String d, int rSold, float hPay) {
        super(id, name, surname);
        this.username = u;
        this.password = p;
        this.hpw = h;
        this.date = d;
        this.recordSold = rSold;
        this.hourPay = hPay;
    }
}

调用超类构造函数以初始化超类。

您可以在两个类中定义这些属性,以便在子类中覆盖它们。 而且,您的Employee构造函数不是应有的方式。 您应该将适应的超级构造函数称为第一条声明。

public class Person {

    protected int       id;
    protected String    name;
    protected String    surname;

    public Person(int id, String name, String surname) {
        this.id      = id;
        this.name    = name;
        this.surname = surname;
    }
}

public class Employee extends Person implements Serializable {
    private String  username;
    private String  password;
    private String  date;
    private int     hpw;
    private int     recordSold;
    private float   hourPay;

    public Employee(String username, String name, String surname, String pswd, int id,
            int hpw, String date, int rSold, float hPay) {
        super(id,name,surname);
        this.username   = username;
        this.password   = pswd;
        this.hpw        = hpw;
        this.date       = date;
        this.recordSold = rSold;
        this.hourPay    = hPay;
    }
}

在您的构造函数中,我考虑了一种最佳做法,就是为此参数赋予与属性名称相同的名称来初始化和区分它们,这要归功于this 有些人也使用相同的名称,只是他们在类的所有成员的开头添加了_ 在任何情况下,当它们表示的变量具有特殊含义(姓,名)时,请勿使用无意义的名称,例如“ s”,“ n”等。 保留这些名称,例如,不带任何特定语义的局部变量(n将是整数,s将是String ...)。

您尚未初始化这些变量,这就是为什么它要为这些变量返回默认值。 在Java中,以下是变量的默认值。

int -> 0
String -> null (because  String is Object in Java)

在您的示例中,您不需要tu use super来访问在超类中定义的属性,因为您正在使用它们的包可见性(而且似乎都在同一个包中)。

但是,这不是编写Java代码的正确方法。

您应该为属性定义可见性。 在大多数情况下,建议使用private可见性并定义getter和setter方法来访问它们:

public class Person {
    private int id;
    private String name;
    private String surname;

    public Person() {}

    public Person(int id, String name, String surname) {
        this.id = id;
        this.name = name;
        this.surname = surname;
    }

    public int getId() {
        return id;
    }

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

    // And so on...
}

在子类中,只需调用getId()setId(...)即可访问Id属性。 无需调用super.getId() 由于Employee扩展了Person ,因此它可以访问其所有公共的,受保护的(和程序包在同一个程序包中)(如果程序包在同一个程序包中)所有属性和方法。

这意味着在您当前的代码中,您可以简单地编写name = n而不是super.name = n

public class Employee extends Person implements Serializable {
    private String username;
    private String password;
    private String date;
    private int hpw;
    private int recordSold;
    private float hourPay;

    public Employee() {}

    public Employee(String username, String name, String surname, String password, int id, int hpw, String date, int rSold, float hPay) {
        super(id, name, surname);
        this.username = username;
        this.password = password;
        this.hpw = hpw;
        this.date = date;
        this.recordSold = rSold;
        this.hourPay = hPay;
    }

    public String getUsername() {
        return username;
    }

    public void setUsername(String username) {
        this.username = username;
    }

    // And so on...
}

现在使用这些类,您可以编写如下代码:

Employee e = new Employee("user3149152", "Ulrich", "Ser", "passwd", 1234, 0, "2014/08/13", 0, 0);
System.out.println("Employee " + e.getName() + ' ' + e.getSurname() + " has for id " + e.getId() + '.'); 

作为参考,该代码甚至可以与您当前的代码一起使用。 它打印:

Employee Ulrich Ser has for id 1234.

暂无
暂无

声明:本站的技术帖子网页,遵循CC BY-SA 4.0协议,如果您需要转载,请注明本站网址或者原文地址。任何问题请咨询:yoyou2525@163.com.

 
粤ICP备18138465号  © 2020-2024 STACKOOM.COM