Getter/Setter (组合、Java、作业)

4

我有一个名为Person的类,基本上长这样:

public class Person
{
    String firstName;
    String lastName;
    String telephone;
    String email;

    public Person()
    {
       firstName = "";
       lastName = "";
       telephone = "";
       email = "";
    }

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

    public String getFirstName()
    {
        return firstName;
    }

    public void setFirstName(String firstName)
    {
        this.firstName = firstName;
    }
 ....

使用那个类,我设置了一个抽象类称为Loan,它的外观如下:

public abstract class Loan
{   
    public void setClient(Person client)
    {
        this.client = client;
    }

    public Person getClient()
    {
        return client;
    }

    public void setLoanId(int nextId)
    {
        loanId = nextId;
        nextId++;
    }

    public int getLoanId()
    {
        return loanId;
    }

    public void setInterestRate(double interestRate)
    {
        this.interestRate = interestRate;
    }

    public double getInterestRate()
    {
        return interestRate;
    }

    public void setLoanLength(int loanLength)
    {
        this.loanLength = loanLength;
    }

    public int getLoanLength()
    {
        return loanLength;
    }

    public void setLoanAmount(double loanAmount)
    {
        this.loanAmount = loanAmount;
    }

    public double getLoanAmount(double loanAmount)
    {
        return loanAmount;
    }

    private Person client;
    private int loanId;
    private double interestRate;
    private int loanLength;
    private double loanAmount;
    private static int nextId = 1;

}

我需要扩展Loan类,创建一个CarLoan类,代码如下:

public class CarLoan extends Loan
{
    public CarLoan(Person client, double vehiclePrice, double downPayment, double salesTax,
                    double interestRate, CAR_LOAN_TERMS length)
    {
        super.setClient(client);
        super.setInterestRate(interestRate);
        this.client = client;
        this.vehiclePrice = vehiclePrice;
        this.downPayment = downPayment;
        this.salesTax = salesTax;
        this.length = length;

    }

    public void setVehiclePrice(double vehiclePrice)
    {
        this.vehiclePrice = vehiclePrice;
    }

    public double getVehiclePrice()
    {
        return vehiclePrice;
    }

    public void setDownPayment(double downPayment)
    {
        this.downPayment = downPayment;
    }

    public double getDownPayment()
    {
        return downPayment;
    }

    public void setSalesTax(double salesTax)
    {
        this.salesTax = salesTax;
    }

    public double getSalesTax()
    {
        return salesTax;
    }

    public String toString()
    {
        return getClass().getName() + "[vehiclePrice = " + vehiclePrice + '\n' 
                                        + "downPayment = " + downPayment + '\n'
                                        + "salesTax = " + salesTax 
                                        + "]";
    }

    public enum CAR_LOAN_TERMS {TWO_YEAR, THREE_YEAR, SIX_YEAR};
    private double vehiclePrice;
    private double downPayment;
    private double salesTax;

几个问题。

(a) 根据我在Person类中的设置,我在Loan类中所做的设置客户的操作是正确的吗?(例如this.client = client)

(b) 我可以在一个方法中两次调用super吗?我必须从CarLoan类的构造函数中设置Loan类中的两个属性,并且我认为这是一种方法。

(c) 在构造函数或getter/setter方法中,是否必须以不同方式设置枚举类型的属性?在我的CarLoan类中,(this.length = length)会出现错误,我不确定枚举值应该如何设置。谢谢!


@Crystal:在“CarLoan”的构造函数的第三行是否出现了编译错误?“CarLoan”类不应该直接访问“Loan”的“client”字段,因为该字段对于“Loan”类来说是私有的。 - Matthew T. Staebler
3个回答

2

好的,按顺序:

  1. setClient 看起来完全没问题。没有任何问题。但是你要避免直接在 CarLoan 构造函数中设置 this.client —— 感谢 @Gabriel 和 @Aeth,你已经调用了 setClient 方法。
  2. 当然,你可以随意使用 super 访问父类方法。你需要小心的是调用超类的 构造函数,你只能在子类构造函数的开头调用一次。 super != super()
  3. 不,this.length = length 没问题。问题在于你没有一个叫做 length 的字段。你可能需要添加一个这样的字段。

看起来不太好,客户端字段设置了两次,而且我不确定在构造函数中调用非静态方法是否可以。 - Gabriel Ščerbák
@Samir Talwar 首先是setClient调用,然后是直接客户端分配。 - Gabriel Ščerbák
1
@Samir: CarLoan 的构造函数中设置了两次 Loanclient。第一次是在第一行调用 super.setClient(client),第二次是在第三行的 this.client = client 中。 - Matthew T. Staebler
1
@Gabriel:从构造函数中调用非静态方法并不是本质上的错误。然而,建议只调用最终的非静态方法。如果您调用了一个非最终的非静态方法,则CarLoan的子类可以重写该方法,并在其中尝试访问尚未创建的字段,因为子类实例尚未创建。 - Matthew T. Staebler
@Gabriel,@Aeth:谢谢,我现在看到了。我会编辑答案以匹配。 - Samir Talwar
显示剩余2条评论

1

1) 在类的构造函数和方法之前放置类属性的声明是惯例。

2) 在 CarLoan 类中,语句 this.client = client; 会导致编译错误,因为在 Loan 类中,client 字段被声明为私有字段。(而且那个语句还是多余的,因为你已经使用了 setter 来初始化相同的字段...虽然我觉得你已经知道这点了。)

3) 初始化超类字段的更好的方法是将参数传递给超类构造函数。例如:

public abstract class Loan
{   
    private Person client;
    private double interestRate;

    public Loan(Person client, double interestRate) {
        this.client = client;
        this.interestRate = interestRate;
    }
    ...
}

public class CarLoan extends Loan
{   
    ...

    public CarLoan(Person client, double vehiclePrice, double downPayment, double salesTax,
                    double interestRate, CAR_LOAN_TERMS length)
    {
        super(client, interestRate); 
        this.vehiclePrice = vehiclePrice;
        ...
    }
}

这种方法更好的原因在于,Loan类负责其初始化,不依赖于各个子类构造函数完成任务。(如果您向Loan添加一个额外的字段,并将相应参数添加到Loan构造函数中,则编译器会提醒您修改所有子类构造函数以在super构造函数链接中提供初始值。如果子类负责在初始化期间设置基类中的字段,则编译器不会注意到您忘记添加新的setter调用的情况。)

4) 如果您在构造函数中调用方法,最好的做法是确保它们不能在子类中被覆盖。(不完全错误的是,这些方法被覆盖,但有些事情可能会出错。在构造函数中调用可能被覆盖的方法会使您的代码变得脆弱。)

5) 如果这是生产代码,则使用floatdouble表示货币值将是大忌!


0
回答问题(c),我认为你之所以出现错误,是因为你需要在已经定义的变量下面定义长度(length)。

网页内容由stack overflow 提供, 点击上面的
可以查看英文原文,
原文链接