更新時(shí)間:2022-11-28 10:21:11 來源:動(dòng)力節(jié)點(diǎn) 瀏覽1525次
似乎抽象類和構(gòu)造函數(shù)可能不兼容的。構(gòu)造函數(shù)方法被稱為實(shí)例化一個(gè)類時(shí),和一個(gè)抽象類不能實(shí)例化。
在本文中,我們將看到為什么抽象類可以有構(gòu)造函數(shù)和如何使用它們?cè)谧宇悓?shí)例化提供了好處。
當(dāng)一個(gè)類不申報(bào)任何構(gòu)造函數(shù),編譯器會(huì)創(chuàng)建一個(gè)默認(rèn)的構(gòu)造函數(shù)。這也適用于抽象類。即使沒有顯式的構(gòu)造函數(shù),抽象類有一個(gè)默認(rèn)的構(gòu)造函數(shù)。
在一個(gè)抽象類,它的后代可以使用超級(jí)調(diào)用抽象默認(rèn)構(gòu)造函數(shù)():
public abstract class AbstractClass {
// compiler creates a default constructor
}
public class ConcreteClass extends AbstractClass {
public ConcreteClass() {
super();
}
}
我們可以聲明一個(gè)構(gòu)造函數(shù)沒有參數(shù)在一個(gè)抽象類。它會(huì)覆蓋默認(rèn)的構(gòu)造函數(shù),以及任何子類創(chuàng)建將稱之為第一建設(shè)鏈。
讓我們驗(yàn)證這一行為有兩個(gè)抽象類的子類:
public abstract class AbstractClass {
public AbstractClass() {
System.out.println("Initializing AbstractClass");
}
}
public class ConcreteClassA extends AbstractClass {
}
public class ConcreteClassB extends AbstractClass {
public ConcreteClassB() {
System.out.println("Initializing ConcreteClassB");
}
}
讓我們看看輸出得到當(dāng)調(diào)用新的ConcreateClassA ():
初始化AbstractClass
而輸出調(diào)用新的ConcreteClassB()將會(huì)是:
初始化AbstractClass
初始化ConcreteClassB
(1)安全初始化
聲明一個(gè)抽象的不帶參數(shù)的構(gòu)造函數(shù)可以有利于安全初始化。
以下計(jì)數(shù)器類計(jì)數(shù)自然數(shù)的超類。我們需要它的值從0開始。
讓我們來看看我們可以使用一個(gè)參數(shù)構(gòu)造函數(shù)來確保安全的初始化:
public abstract class Counter {
int value;
public Counter() {
this.value = 0;
}
abstract int increment();
}
我們SimpleCounter子類實(shí)現(xiàn)增量和+ +運(yùn)算符()方法。它由一個(gè)在每個(gè)增量的價(jià)值調(diào)用:
public class SimpleCounter extends Counter {
@Override
int increment() {
return ++value;
}
}
請(qǐng)注意,SimpleCounter不申報(bào)任何構(gòu)造函數(shù)。成立依賴柜臺(tái)默認(rèn)的無參數(shù)構(gòu)造函數(shù)被調(diào)用。
下面的單元測(cè)試演示了安全屬性被初始化的值構(gòu)造函數(shù):
@Test
void givenNoArgAbstractConstructor_whenSubclassCreation_thenCalled() {
Counter counter = new SimpleCounter();
assertNotNull(counter);
assertEquals(0, counter.value);
}
(2)阻止訪問
計(jì)數(shù)器的初始化工作正常,但是讓我們想象我們不想讓子類覆蓋這個(gè)安全初始化。
首先,我們需要阻止子類的構(gòu)造函數(shù)私有訪問:
private Counter() {
this.value = 0;
System.out.println("Counter No-Arguments constructor");
}
其次,讓我們創(chuàng)建另一個(gè)調(diào)用子類的構(gòu)造函數(shù):
public Counter(int value) {
this.value = value;
System.out.println("Parametrized Counter constructor");
}
最后,我們需要SimpleCounter覆蓋參數(shù)化構(gòu)造函數(shù),否則,它不會(huì)編譯:
public class SimpleCounter extends Counter {
public SimpleCounter(int value) {
super(value);
}
// concrete methods
}
注意編譯器預(yù)計(jì)我們稱之為超級(jí)構(gòu)造函數(shù)(值),限制訪問我們的私人參數(shù)構(gòu)造函數(shù)。
最常見的一種使用抽象類的構(gòu)造函數(shù)是為了避免冗余。讓我們創(chuàng)建一個(gè)示例使用汽車,看看我們可以利用參數(shù)化構(gòu)造函數(shù)。
我們從一個(gè)抽象的汽車類來代表所有類型的汽車。我們還需要知道多少旅行距離屬性:
public abstract class Car {
int distance;
public Car(int distance) {
this.distance = distance;
}
}
我們的超類看起來很好,但我們不希望距離屬性被初始化一個(gè)非零值。我們也要防止子類改變財(cái)產(chǎn)或覆蓋的距離參數(shù)化構(gòu)造函數(shù)。
讓我們看一下如何限制距離和安全地使用構(gòu)造函數(shù)來初始化:
public abstract class Car {
private int distance;
private Car(int distance) {
this.distance = distance;
}
public Car() {
this(0);
System.out.println("Car default constructor");
}
// getters
}
現(xiàn)在,我們距離屬性和參數(shù)化構(gòu)造函數(shù)是私有的。有公共汽車默認(rèn)構(gòu)造函數(shù)()代表私有構(gòu)造函數(shù)來初始化的距離。
財(cái)產(chǎn)使用我們的距離,讓我們添加一些行為來獲取和顯示汽車的基本信息:
abstract String getInformation();
protected void display() {
String info = new StringBuilder(getInformation())
.append("\nDistance: " + getDistance())
.toString();
System.out.println(info);
}
所有子類都需要提供一個(gè)實(shí)現(xiàn)getInformation(),和顯示()方法將使用它來打印所有的細(xì)節(jié)。
現(xiàn)在讓我們創(chuàng)建ElectricCar和FuelCar子類:
public class ElectricCar extends Car {
int chargingTime;
public ElectricCar(int chargingTime) {
this.chargingTime = chargingTime;
}
@Override
String getInformation() {
return new StringBuilder("Electric Car")
.append("\nCharging Time: " + chargingTime)
.toString();
}
}
public class FuelCar extends Car {
String fuel;
public FuelCar(String fuel) {
this.fuel = fuel;
}
@Override
String getInformation() {
return new StringBuilder("Fuel Car")
.append("\nFuel type: " + fuel)
.toString();
}
}
讓我們看看這些子類行動(dòng):
ElectricCar electricCar = new ElectricCar(8);
electricCar.display();
FuelCar fuelCar = new FuelCar("Gasoline");
fuelCar.display();
產(chǎn)生的輸出的樣子:
Car default constructor
Electric Car
Charging Time: 8
Distance: 0
Car default constructor
Fuel Car
Fuel type: Gasoline
Distance: 0
像任何其他類在Java中,抽象類可以有構(gòu)造函數(shù),即使他們只是從具體的子類。如果大家想了解更多相關(guān)知識(shí),不妨來關(guān)注一下本站的Java基礎(chǔ)教程,里面還有更豐富的知識(shí)等著大家去學(xué)習(xí),希望對(duì)大家能夠有所幫助哦。
0基礎(chǔ) 0學(xué)費(fèi) 15天面授
有基礎(chǔ) 直達(dá)就業(yè)
業(yè)余時(shí)間 高薪轉(zhuǎn)行
工作1~3年,加薪神器
工作3~5年,晉升架構(gòu)
提交申請(qǐng)后,顧問老師會(huì)電話與您溝通安排學(xué)習(xí)