多态
含义:顾名思义,是指对象的多种形态,是对象多种表现形式的体现。
多态是建立在封装和继承之上 。
多态存在的三个必要条件
1.必须存在 继承 或 实现。
2.子类中重写父类的方法。
3.父类引用指向子类对象(向上转型)。
- 多态有两种:方法的多态和对象的多态。
方法的多态
方法的重写和重载就是方法的多态的表现形式。
class Father { //父类
public void eat() {
System.out.println("吃米饭");
}
public void eat(String food) {
System.out.println("父类吃:" + food);
}
}
class Son extends Father{ //子类
@Override
public void eat() {
System.out.println("吃面条");
}
@Override
public void eat(String food) {
System.out.println("子类吃:" + food);
}
}
public class Demo1 {
public static void main(String[] args) {
Father father = new Father();
father.eat();
Father father1 = new Father();
father1.eat("吃牛肉");
Son son = new Son();
son.eat();
Son son1 = new Son();
son1.eat("鸡肉");
}
}
对象的多态
- 一个对象的编译类型和运行类型是不同的
- 编译类型是在定义对象的时候就已经确定好的,但运行类型是可以改变的
- 编译类型看 “=” 的左边,运行类型看 “=” 的右边
父类的引用指向子类的对象
Animal an = new Tiger();
Animal an1 = new Cat();
class Animal {
public void cry() {
System.out.println("动物的叫声");
}
}
class Tiger extends Animal {
@Override
public void cry() {
System.out.println("老虎的叫声很大");
}
}
class Cat extends Animal {
@Override
public void cry() {
System.out.println("小猫的叫声很小");
}
}
public class Demo1 {
public static void main(String[] args) {
Animal an = new Tiger(); //Animal类的引用指向Tiger类引用
an.cry();
Animal an1 = new Cat();
an1.cry();
}
}
在开发中,一个方法的参数是父类的引用。但是真正传的值是子类的对象。 将子类的对象赋值给了父类的引用。
//面馆类
class NoodleShop {
public void choice(Nodle nodle) {
nodle.make();
}
}
//面条类
class Nodle {
private String name;
private double price;
public String getName() {
return name;
}
public void setName(String name) {
this.name = name;
}
public double getPrice() {
return price;
}
public void setPrice(double price) {
this.price = price;
}
public void make() {
}
}
//牛肉面类
class BeefNoodles extends Nodle {
@Override
public void make() {
System.out.println("制作面条的名称:" + getName() + ",价格:" + getPrice());
}
}
//鸡肉面类
class ChickenNoodles extends Nodle {
@Override
public void make() {
System.out.println("制作面条的名称:" + getName() + ",价格:" + getPrice());
}
}
public class Demo1 {
public static void main(String[] args) {
NoodleShop noodleShop = new NoodleShop();
Nodle nodle = new BeefNoodles();
nodle.setName("牛肉面");
nodle.setPrice(58.1);
noodleShop.choice(nodle);
Nodle nodle1 = new ChickenNoodles();
nodle1.setName("鸡肉面");
nodle1.setPrice(49.9);
noodleShop.choice(nodle1);
}
}
多态的转型
向上转型和向下转型。
向上转型
本质:父类的引用指向子类对象 。
语法格式:
父类 父类引用 = new 子类();
父类的引用可以调用父类的所有成员方法,可以调用子类的重写父类的方法,但是不能调用子类独有的方法。
class Person {
public void eat () {
}
}
class Student extends Person {
@Override
public void eat() { //子类重写父类的方法
System.out.println("学生吃饭,吃披萨");
}
public void sleep () {
System.out.println("中午不睡下午崩溃!!!");
}
}
public class Demo1 {
public static void main(String[] args) {
Person person = new Student(); //向上转型
person.eat();
//person.sleep(); //父类无法调用子类独有的方法
}
}
向下转型
需要强转
- 注意点:先向上转型,再向下转型
语法格式:
父类类型 父类引用 = new 子类(); //父类引用指向了子类的对象,子类赋值给父类引用
子类类型 子类引用 = (子类类型)父类的引用;向下转型 //将父类的引用赋值给子类,父类赋值给子类引用
//引用上面的animal、tiger和cat
Animal a = new Tiger();
Tiger tiger = ((Tiger) a);
tiger.cry();
//输出 老虎的叫声很大
Cat cat = ((Cat) a);
cat.cry();
// 报错
Animal a1 = new Animal();
Cat cat1 = ((Cat) a1);
cat1.cry();
// 报错
第一段代码之所以不报错,是因为先将子类对象赋值给父类引用了,a本身就是Tiger类的对象,在此之后再向下转型。
而a1为父类Animal的对象,它不能被向下转型为任何子类对象。