多態(tài)是面向?qū)ο笕筇卣髦?/h1>
一、什么是多態(tài)
對象在運行過程中的多種形態(tài)
二、多態(tài)分類
1.方法的重載和重寫
2.對象的多態(tài)性
例如:用父類的引用指向子類對象(用大的類型去接受小的類型,向上轉(zhuǎn)型、自動轉(zhuǎn)換)
Chicken home= new HomeChicken();
結(jié)論:
在編程時針對抽象類型的編寫代碼,稱為面向抽象編程(或面向接口編程)
父類通常都定義為抽象類、接口
對象的多態(tài)性
對象多態(tài)性是從繼承關(guān)系中的多個類而來
向上轉(zhuǎn)型:將子類實例轉(zhuǎn)為父類引用
格式:父類 父類對象= 子類實例; 自動轉(zhuǎn)換
示例代碼:
public class Demo {
public static void main(String[] args) {
//用父類的引用指向子類對象(用大的類型來表示小的類型),自動轉(zhuǎn)換(向上轉(zhuǎn)型)
Chicken hc = new HomeChicken("小米");
// hc.eat();
YeChicken yc = new YeChicken("大米");
// yc.eat();
// hc=yc;
// hc.eat();
eat(hc);
eat(yc);
}
//抽象(粒度)面向抽象編程(面向接口編程)
public static void eat(Chicken c)
{
System.out.println("雞愛吃什么");
c.eat();
}
}
//雞
abstract class Chicken{
private String name;
public Chicken(){}
public Chicken(String name)
{
this.name = name;
}
public void setName(String name) {
this.name = name;
}
public String getName() {
return name;
}
public abstract void eat();
}
//家雞
class HomeChicken extends Chicken{
public HomeChicken(String name)
{
super(name);
}
@Override
public void eat() {
System.out.println(this.getName()+"我愛吃米");
}
}
//野雞
class YeChicken extends Chicken{
public YeChicken(String name)
{
super(name);
}
@Override
public void eat() {
System.out.println(this.getName()+"我愛吃蟲");
}
}
運行效果:

image.png
向下轉(zhuǎn)型:將父類實例轉(zhuǎn)為子類實例
格式:子類 子類對象= (子類)父類實例; 強制轉(zhuǎn)換
代碼:
public class Demo {
public static void main(String[] args) {
//用父類的引用指向子類對象(用大的類型來表示小的類型),自動轉(zhuǎn)換(向上轉(zhuǎn)型)
Chicken hc = new HomeChicken("小米");
YeChicken yc = new YeChicken("大米");
Chicken jc = new JianChicken();
eat(jc);
}
//抽象(粒度)面向抽象編程(面向接口編程)
public static void eat(Chicken c)
{
System.out.println("雞愛吃什么");
c.eat();
JianChicken jjc = (JianChicken)c;
//大的類型轉(zhuǎn)換為小的類型,強制轉(zhuǎn)換(向下轉(zhuǎn)型)
jjc.sing();
}
}
//雞
abstract class Chicken{
private String name;
public Chicken(){}
public Chicken(String name)
{
this.name = name;
}
public void setName(String name) {
this.name = name;
}
public String getName() {
return name;
}
public abstract void eat();
}
//家雞
class HomeChicken extends Chicken{
public HomeChicken(String name)
{
super(name);
}
@Override
public void eat() {
System.out.println(this.getName()+"我愛吃米");
}
}
//野雞
class YeChicken extends Chicken{
public YeChicken(String name)
{
super(name);
}
@Override
public void eat() {
System.out.println(this.getName()+"我愛吃蟲");
}
}
class JianChicken extends Chicken{
@Override
public void eat() {
System.out.println("我不吃東西");
}
public void sing()
{
System.out.println("唧唧復(fù)唧唧,我是尖叫雞");
}
}
運行效果:

image.png
三、多態(tài)性小結(jié)
1.方法的重載與重寫就是方法的多態(tài)性表現(xiàn)
2.多個子類就是父類中的多種形態(tài)
3.父類引用可以指向子類對象,自動轉(zhuǎn)換
4.子類對象指向父類引用需要強制轉(zhuǎn)換(注意:類型不對會報異常)
5.在實際開發(fā)中盡量使用父類引用(更利于擴展)
四、instanceof關(guān)鍵字
1.instanceof是用于檢查對象是否為指定的類型,通常在把父類引用強制轉(zhuǎn)換為子類引用時要使用,以避免發(fā)生類型轉(zhuǎn)換異常(ClassCastException)
//當我們需要把父類的實例強制轉(zhuǎn)換為子類引用時,為了避免類型轉(zhuǎn)換異常ClassCastException
//那么我們需要在轉(zhuǎn)換之前做類型檢查(判斷)
if(c instanceof JianChicken) //成立的條件是,對象本身及對象的父類型,都可以通過檢查
{
JianChicken jjc = (JianChicken)c;
//大的類型轉(zhuǎn)換為小的類型,強制轉(zhuǎn)換(向下轉(zhuǎn)型)
jjc.sing();
}
示例代碼:
public class Demo {
public static void main(String[] args) {
//用父類的引用指向子類對象(用大的類型來表示小的類型),自動轉(zhuǎn)換(向上轉(zhuǎn)型)
Chicken hc = new HomeChicken("小米");
YeChicken yc = new YeChicken("大米");
Chicken jc = new JianChicken();
eat(jc);
eat(hc);
eat(yc);
}
//抽象(粒度)面向抽象編程(面向接口編程)
public static void eat(Chicken c)
{
System.out.println("雞愛吃什么");
c.eat();
//當我們需要把父類的實例強制轉(zhuǎn)換為子類引用時,為了避免類型轉(zhuǎn)換異常ClassCastException
//那么我們需要在轉(zhuǎn)換之前做類型檢查(判斷)
if(c instanceof JianChicken)
{
JianChicken jjc = (JianChicken)c;
//大的類型轉(zhuǎn)換為小的類型,強制轉(zhuǎn)換(向下轉(zhuǎn)型)
jjc.sing();
}
}
}
//雞
abstract class Chicken{
private String name;
public Chicken(){}
public Chicken(String name)
{
this.name = name;
}
public void setName(String name) {
this.name = name;
}
public String getName() {
return name;
}
public abstract void eat();
}
//家雞
class HomeChicken extends Chicken{
public HomeChicken(String name)
{
super(name);
}
@Override
public void eat() {
System.out.println(this.getName()+"我愛吃米");
}
}
//野雞
class YeChicken extends Chicken{
public YeChicken(String name)
{
super(name);
}
@Override
public void eat() {
System.out.println(this.getName()+"我愛吃蟲");
}
}
class JianChicken extends Chicken{
@Override
public void eat() {
System.out.println("我不吃東西");
}
public void sing()
{
System.out.println("唧唧復(fù)唧唧,我是尖叫雞");
}
}
運行效果:

image.png
四、父類設(shè)計法則
1.父類通常情況下都設(shè)計為抽象類或接口,其中優(yōu)先考慮接口,如接口不能滿足才考慮抽象類
2.一個具體的類盡可能不去繼承另一個具體類,這樣的好處是無需檢查對象是否為父類的對象