有 Java 编程相关的问题?

你可以在下面搜索框中键入要查询的问题!

类抽象类超级构造函数(Java)

我有一个非常简单的问题:

假设我有一个抽象类,它代表酒吧里的一个人

public class Person {
    protected String firstName;
    protected String lastName;

    public Person(String firstName, String lastName) {
        this.firstName = firstName;
        this.lastName = lastName;
    }
}

我还有两个扩展个人的课程,比如说一个是调酒师的课程,另一个是顾客的课程

在客户类中,我还需要一个int作为字段表示他的年龄。在调酒师课上,我们没有

另外,对于customer类,我需要一个方法isAdult()

public class Bartender extends Person {
    public Bartender(String firstName, String lastName) {
        this.firstName = firstName;
        this.lastName = lastName;
    }
}

public class Customer extends Person {
private int age;    

    public Customer(String firstName, String lastName, int age) {
        this.firstName = firstName;
        this.lastName = lastName;
        this.age = age;
    }
}

我现在有两个问题:

1)这不起作用,因为我收到消息“隐式超级构造函数Passenger()未定义。必须显式调用另一个构造函数”。 这到底是什么意思? 2) 对于isAdult()方法,我觉得最好的方法是在抽象类Person中实现它,如下所示:

public abstract boolean isAdult();

然后为调酒师提供“始终真实”服务,并为顾客提供年龄检查服务

另一种方法是直接从类人员实现,如下所示:

public boolean isAdult() {
    return (this instanceof Bartender || age > 18);
}

这样行吗?哪种方式更好


共 (5) 个答案

  1. # 1 楼答案

    关于你的第一个问题,请看满是鳗鱼答案的气垫船;对于你的第二个问题,我认为你应该给Person一个“age”属性(每个人都有一个age)和逻辑isAdult实现。如果Bartender真的是Person,它应该有一个年龄。因此,我认为你首先不应该假设Bartender是成年人。在任何调用Person#isAdult的逻辑中,在PersonBartender的情况下,让它假设true

  2. # 2 楼答案

    答1:Java实际上总是调用超类的构造函数。例如:

    class Super{
    }
    
    class Base extends Super{
         public Base(){
              //super() will always be called implicitly if a defaultconstructor is provided by Super
    
              //do something else
         }
    }
    

    这样做是因为基类的结构由基类的结构和超类的结构组成。如果不通过调用超类的构造函数来初始化超类的结构,则可能会发生错误。由于Person不提供defaultconstructor,但无论如何都需要初始化,因此必须使用这两个参数显式调用超级构造函数

    答复2: 这两种方法都可以很好地工作,但我(以及我希望的其他所有人)强烈建议在派生类中单独实现它,以保持所有内容的可扩展性、干净性、可读性以及其他成千上万的原因

  3. # 3 楼答案

    对于第一个问题,请注意:当您创建一个类时,它会自动为您创建该类的默认构造函数。如果你创建了另一个构造函数,你必须自己创建一个默认的构造函数,因为Java认为你知道你现在在做什么。所以,只需将其添加到Person类中:

    public Person(){}
    
  4. # 4 楼答案

    Person有一个使用构造函数定义的参数,没有默认的无参数构造函数。由于子类的超级构造函数必须始终在子构造函数中调用,而且Person没有默认构造函数,因此必须在子构造函数中显式地调用它:

    public Bartender(String firstName, String lastName) {
        super(firstName, lastName);
    
        // don't do this:
        // this.firstName = firstName;
        // this.lastName = lastName;
    }
    

    public Customer(String firstName, String lastName, int age) {
        super(firstName, lastName);
        this.age = age;
    }
    

    关于isAdult(),您可以在Customer类中使用此方法,而不在Bartender中使用。或者,如果super必须有这个方法,如果有人在调酒师身上调用它,你可以抛出一个异常,因为它不应该这样调用

  5. # 5 楼答案

    问题的第二部分: 在超类中抽象isAdult(),在子类中提供特定的实现。如果有几个子类具有类似的实现,那么您可以考虑将该实现放在父类中,并适当地重写。

    父类永远不应该知道自己的子类,因此要避免让父类检查子类的实例