多态是面向对象三大特征之一
一、什么是多态
对象在运行过程中的多种形态
二、多态分类
1.方法的重载和重写
2.对象的多态性
例如:用父类的引用指向子类对象(用大的类型去接受小的类型,向上转型、自动转换)
Chicken home= new HomeChicken();
结论:
在编程时针对抽象类型的编写代码,称为面向抽象编程(或面向接口编程)
父类通常都定义为抽象类、接口
对象的多态性
对象多态性是从继承关系中的多个类而来
向上转型:将子类实例转为父类引用
格式:父类 父类对象= 子类实例; 自动转换
示例代码:
public class Demo {
public static void main(String[] args) {
//用父类的引用指向子类对象(用大的类型来表示小的类型),自动转换(向上转型)
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()+"我爱吃虫");
}
}
运行效果:
向下转型:将父类实例转为子类实例
格式:子类 子类对象= (子类)父类实例; 强制转换
代码:
public class Demo {
public static void main(String[] args) {
//用父类的引用指向子类对象(用大的类型来表示小的类型),自动转换(向上转型)
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;
//大的类型转换为小的类型,强制转换(向下转型)
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("唧唧复唧唧,我是尖叫鸡");
}
}
运行效果:
三、多态性小结
1.方法的重载与重写就是方法的多态性表现
2.多个子类就是父类中的多种形态
3.父类引用可以指向子类对象,自动转换
4.子类对象指向父类引用需要强制转换(注意:类型不对会报异常)
5.在实际开发中尽量使用父类引用(更利于扩展)
四、instanceof关键字
1.instanceof是用于检查对象是否为指定的类型,通常在把父类引用强制转换为子类引用时要使用,以避免发生类型转换异常(ClassCastException)
//当我们需要把父类的实例强制转换为子类引用时,为了避免类型转换异常ClassCastException
//那么我们需要在转换之前做类型检查(判断)
if(c instanceof JianChicken) //成立的条件是,对象本身及对象的父类型,都可以通过检查
{
JianChicken jjc = (JianChicken)c;
//大的类型转换为小的类型,强制转换(向下转型)
jjc.sing();
}
示例代码:
public class Demo {
public static void main(String[] args) {
//用父类的引用指向子类对象(用大的类型来表示小的类型),自动转换(向上转型)
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();
//当我们需要把父类的实例强制转换为子类引用时,为了避免类型转换异常ClassCastException
//那么我们需要在转换之前做类型检查(判断)
if(c instanceof JianChicken)
{
JianChicken jjc = (JianChicken)c;
//大的类型转换为小的类型,强制转换(向下转型)
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("唧唧复唧唧,我是尖叫鸡");
}
}
运行效果:
四、父类设计法则
1.父类通常情况下都设计为抽象类或接口,其中优先考虑接口,如接口不能满足才考虑抽象类
2.一个具体的类尽可能不去继承另一个具体类,这样的好处是无需检查对象是否为父类的对象