我有一个抽象类Compartment
,其中包含变量label
tariff
totalSeats
和seatsAvailable
,如下所示。我通过从子类super()
的构造函数中调用FirstClassCompartment
来设置这些变量。关于我的代码我几乎没有问题。
首先,这是使用超类构造函数设置变量的正确方法,或者我应该在超类中创建一个setter方法来设置这些变量。
其次,直接访问超类变量而不使用getter / setter方法是不好的编码。
最后,超类中变量seatsAvailable
的值取决于子类中的变量seatsReserved
,如seatsAvailable = totalSeats - seatsReserved
。这可能导致代码维护或未来的灵活性问题吗?
public abstract class Compartment {
protected final char label;
protected final double tariff;
protected final int totalSeats;
protected int seatsAvailable;
public Compartment(char label, double tariff, int totalSeats) {
this.label = label;
this.tariff = tariff;
this.totalSeats = totalSeats;
}
public char getLabel() {
return label;
}
public int getTotalSeats() {
return totalSeats;
}
public void setSeatsAvailableLessByOne() {
seatsAvailable--;
}
public abstract int getSeatsAvailable();
public abstract double getTariff();
}
public class FirstClassCompartment extends Compartment {
protected final int seatsReserved;
public FirstClassCompartment(char label, double tariff, int totalSeats, int seatsReserved) {
super(label, tariff, totalSeats);
this.seatsReserved = seatsReserved;
seatsAvailable = totalSeats - seatsReserved;
}
@Override
public double getTariff() {
return tariff + tariff * .13;
}
@Override
public int getSeatsAvailable() {
return seatsAvailable;
}
}
答案 0 :(得分:1)
第一个问题:这绝对是正确的方法。调用超类构造函数,并传递相关参数。
第二个问题:这在某种程度上是一种风格。最好不要让所有字段直接供所有字段使用,因此您不希望它们为public
,但将它们提供给您自己的子类并不是灾难性的。但是,通过getter和setter使它们可用是非常合理的,当然如果你想让子类可以读取但不可写的字段,那么getter就是合适的。
第三个问题:这里没问题。超类是abstract
,因此您希望子类实现填补一些空白。但由于seatsAvailable
逻辑是如此简单(减法),你可能会想到完全摆脱seatsAvailable
字段,而只是
@Override
public int getSeatsAvailable() {
return totalSeats - seatsReserved;
}
这样,它会在飞行中计算,你不必担心让这个字段与其他字段保持同步。
答案 1 :(得分:0)
对我来说很好,我可能会将方法setSeatsAvailableLessByOne
重命名为更有意义的内容,例如decrementSeatsAvailable
,如果你想要它的话。
修改强>
你说seatsAvailable
是多余的,你是对的。您可以将seatsReserved
和派生值移动到超类tho'。在这些特定情况下,不太可能有其他方法来实现getSeatsAvailable
方法,即使有,也可以覆盖它。
答案 2 :(得分:0)
我用“' package'来声明我的字段能见度。它是默认的可见性,可以通过inhered类和相同的包类访问它。当你进行单元测试时,它会有很大帮助,因为测试是在同一个包中编写的。
在我看来,不分青红皂白地使用getter / setter打破了封装。您可能会默认显示所有字段,可能不需要。
如果你的变量在构造函数中只设置了一次,那么它们应该是#final;#。
如果setter有一些逻辑,并且将来你可能需要覆盖它,然后使它可以覆盖,但在构造函数中使用可覆盖的方法不是一个好习惯。