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

时间:2015-03-13 21:47:52

标签: java class abstract

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

我们说我有一个代表一个人在酒吧里的抽象课。

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

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

我还有2个课程可以扩展Person,让我们说一个调酒师课程和一个客户课程。

在客户的课堂上,我还想要一个代表他的年龄的int作为一个领域。在调酒师课上,我们没有。

另外,对于客户类,我想要一个方法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();

然后实施它,让Bartenders一直回归,并让客户检查他们的年龄。

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

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

这会有效吗?哪种方式更好?

5 个答案:

答案 0 :(得分:6)

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中使用此方法。或者,如果超级必须有这种方法,如果有人在调酒师上调用它,你可以抛出异常,因为它不应该被这样调用。

答案 1 :(得分:1)

回答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,但需要进行初始化,因此必须使用这两个参数显式调用superconstructor。

答案2: 它们都可以正常工作,但我(以及其他所有人,我希望)会强烈建议在派生类中单独实现它,以保持一切可扩展,清晰,可读和其他数千个原因。

答案 2 :(得分:0)

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

public Person(){}

答案 3 :(得分:0)

关于你的第一个问题,请参阅气垫船满鳗鱼的答案;对于你的第二个问题,我认为你应该给Person一个"年龄"财产(每个人都有一个年龄)和逻辑isAdult实施。如果Bartender确实是Person,则应该有一个年龄。因此,我认为你不应该认为Bartender首先是成年人。无论您调用Person#isAdult的逻辑是什么,如果truePerson,请假设为Bartender

答案 4 :(得分:0)

问题的第二部分: 在超类中创建isAdult()抽象,在子类中提供特定的实现。如果事实证明几个子类具有类似的实现,那么您可以考虑将该实现放在父类中并根据需要进行覆盖。

父类应该永远不会知道他们的子类,因此应该避免让父母检查子例子。