### 向上轉型與向下轉型
> 向上轉型:將子類轉型為父類;
> 向下轉型:將父類轉型為子類;

#### 向上轉型的 **特點**
- 語法
```
<父類型> <引用變量名> = new <子類型>();
```
- 好處:隱藏了子類型,提高了代碼的擴展性;
- 壞處:只能使用父類的功能,不能使用子類的特有功能,功能被限定;
- 場景:使用父類的功能即可完成的操作,不需要面對子類類型;
```java
/**
* 向上轉型的缺點
*/
public class Car {
/**
* 開車
*/
public void run() {
System.out.println("父類的run()");
}
}
/**
* 蔚來
*/
class Nio extends Car {
@Override
public void run() {
System.out.println("子類的run()");
}
/**
* 汽車的價格
*/
public void price() {
System.out.println("子類汽車的價格");
}
public static void main(String[] args) {
// 習慣
Nio nio = new Nio();
nio.run();
nio.price();
System.out.print("\n");
// 向上轉型
Car car = new Nio();
car.run();
// car.price();
}
}
```
運行程序后輸出的內容:
> 使用car實例調用price的時候,提示`Cannot resolve method 'price' in 'Car'`
- 代碼中*Car car = new Nio()*,我們使用了向上轉型,但是由于進行了向上轉型,就失去了使用父類中所沒有的方法的“權利”,不能調用price()方法;
- 那向上轉型到底有什么用呢?
```java
/**
* 向上轉型的優點
*/
public class Car {
/**
* 開車
*/
public void run() {
System.out.println("父類的run()");
}
public void tune(Car car) {
// 插鑰匙,擰鑰匙,開火,踩離合,加油門,松離合,起步走
car.run();
}
}
class Tesla extends Car{
@Override
public void run() {
System.out.println("Tesla的run()");
}
/**
* 汽車的價格
*/
public void price() {
System.out.println("Tesla汽車的價格");
}
}
/**
* 蔚來
*/
class Nio extends Car {
@Override
public void run() {
System.out.println("Nio的run()");
}
/**
* 汽車的價格
*/
public void price() {
System.out.println("Nio汽車的價格");
}
public static void main(String[] args) {
// 向上轉型缺點 - 不能使用子類擴展的price功能
Car car = new Nio();
car.run();
// car.price();
System.out.print("\n");
// 習慣
Nio nio = new Nio();
nio.run();
nio.price();
System.out.print("\n");
// 向上轉型的優點
car.tune(nio);
Tesla tesla = new Tesla();
// 方便擴展
car.tune(tesla);
}
}
```
##### 向上轉型總結
向上轉型雖然使代碼變得簡潔,體現了JAVA的抽象編程思想,但是也出現了上面提到的子類無法調用其獨有的方法,這要怎么解決呢?所以就有了與之對應的向下轉型,彌補了向上轉型所帶來的缺陷。
#### 向下轉型
#### 向上轉型的 **特點**
- 語法
```
<父類型> <引用變量名A> = new <子類型>();
<子類型> <引用變量名> = (子類型)<引用變量名A>;
```
- 好處:可以使用子類型的特有功能;
- 壞處:向下轉型具有風險,容易發生ClassCastException,只要轉換類型和對象不匹配就會發生。可以使用關鍵字instanceof進行解決;
- 場景:泛型類業務;
```java
public class Car {
/**
* 開車
*/
public void run() {
System.out.println("父類的run()");
}
}
class Tesla extends Car {
@Override
public void run() {
System.out.println("Tesla的run()");
}
/**
* 汽車的價格
*/
public void price() {
System.out.println("Tesla汽車的價格");
}
}
class Nio extends Car {
@Override
public void run() {
System.out.println("Nio的run()");
}
/**
* 汽車的價格
*/
public void price() {
System.out.println("Nio汽車的價格");
}
public static void main(String[] args) {
// 先向上轉型
Car[] car = { new Nio(), new Tesla() };
car[0].run();
// car[0].price();
// 后向下轉型
Nio nio = (Nio)car[0];
nio.price();
// 后向下轉型
Tesla tesla = (Tesla) car[1];
tesla.price();
// 不向上轉型
Car car2 = new Car();
((Nio)car2).run();
}
}
```
> 如果不先進行`向上轉型`,直接實例化Car,進行強制性`向下轉型`可以不?

編譯使未報錯,但運行后程序出現錯誤;

*****
這是因為我們實例化了一個父類對象,當我們使用強制轉型轉為`Nio`時,由于子類可以定義自己的方法,父類的域小于子類的域,這個時候我們直接向下轉型就會發生這個錯誤,所以需要*先向上轉型,后向下轉型*。
##### **instanceof**關鍵字
- 語法
```
# 一個對象是否為一個類的實例
**對象名 instanceof 類名**
```

*****
### 參考與引用
[CSDN - 迷棱](https://blog.csdn.net/guchenjun789/article/details/81055317)
[CSDN - yddcc](https://blog.csdn.net/weixin_40601536/article/details/84103029)
[CSDN - TNTZS666](https://blog.csdn.net/TNTZS666/article/details/80274526)