实现多态的两个要素(三个必要条件):

  1. 子类重写父类的方法
  2. 使用父类的类型

三个必要条件:(与两个要素大致相同)

1.继承
2. 重写
3. 父类引用指向子类对象

多态的优点

  1. 消除类型之间的耦合关系
  2. 可替换性
  3. 可扩充性
  4. 接口性
  5. 灵活性
  6. 简化性

或者:

  1. 减少类中代码量
  2. 提高代码的可扩展性和可维护性

多态的实现方式:

  1. Java 重写(Override)与重载(Overload) !!
    方法的重写(Overriding)和重载(Overloading)是java多态性的不同表现,重写是父类与子类之间多态性的一种表现,重载可以理解成多态的具体表现形式
  2. 接口!!!
    同一个接口,使用不同的实例而执不同操作
  3. 抽象类和抽象方法
    同一个行为具有多个不同表现形式或形态的能力

实现多态的两种形式:

  1. 使用父类作为方法形参实现多态
    如:
  2. 03java基础进阶之多态_多态

  3. 使用父类作为方法返回值实现多态
    如:
  4. 03java基础进阶之多态_子类_02

多态的使用:

  1. 父类类型的引用指向子类的对象
  2. 该引用只能调用父类中定义的方法和变量
  3. 如果子类中重写了父类中的一个方法,那么在调用这个方法的时候,将会调用子类中的这个方法(动态连接、动态调用)
  4. 变量不能被重写(覆盖),”重写”的概念只针对方法

向上转型:

子类向父类进行转换(自动转换)

父类 ()  变量名 = new 子类名(;)
就比如:Pet pet = new Dog(); Pet为父类,Dog为子类

向下转型:

父类向子类进行转换(强制转换)

就比如: Dog dog = (Dog) pet;结合 instanceof使用,例子如下。

常与instanceof运算符结合使用(instanceof通常和强制类型转换结合使用)
语法:对象 instanceof 类或接口

public class Master {
public void play(Pet pet){
if (pet instanceof Dog) { //如果传入的是狗狗(比较规则,传入的对象是否为后边对象的子类
或者与后边的对象指的是一个对象)
Dog dog = (Dog) pet;//(强制转换,也就是向下转换)
dog.catchingFlyDisc();
}else if (pet instanceof Penguin) { //如果传入的是企鹅
Penguin pgn = (Penguin) pet;
pgn.swimming();
}
}
}

使用抽象方法和抽象类实现多态:(向上转换)

public abstract class Animal {  // 父类,以抽象来举例
abstract void eat();
}
public class Cat extends Animal { //子类猫,对eat()方法重写
public void eat() {
System.out.println("吃鱼");
}
public void work() { //重新多写了一个work类
System.out.println("抓老鼠");
}
}
public class Dog extends Animal { //子类狗,对eat()方法重写
public void eat() {
System.out.println("吃骨头");
}
public void work() {
System.out.println("看家");
}
}
public static void show(Animal a) {
a.eat();
// 类型判断
if (a instanceof Cat) { // 猫做的事情
Cat c = (Cat)a;
c.work();
} else if (a instanceof Dog) { // 狗做的事情
Dog c = (Dog)a;
c.work();
}
}
public class Test {
public static void main(String[] args) {
show(new Cat()); // 以 Cat 对象调用 show 方法
show(new Dog()); // 以 Dog 对象调用 show 方法

Animal a = new Cat(); // 向上转型, 父类引用 指向子类对象
//编译时检查父类的引用类型
//运行时JVM指定对象类型,调用子类对象方法,前提是父类中定义了该方法
//判断一个实例引用的类型时,使用的是实际类型,而不是声明的类型。a是Cat类型,而不是Animal类型。
a.eat(); // 调用的是 Cat 的 eat()方法
//重写的方法能在运行时调用,而不管编译时引用变量是什么数据类型

Cat c = (Cat)a; // 向下转型
c.work(); // 调用的是 Cat 的 work()方法
}

}

*上边是找别人的,我重新编写了一个,大家可以参考下这个:
*

public class Pet {//父类,宠物类,定义一个共有的方法eat()
public void eat(){
System.out.println("父类吃");
}
}

public class Dog extends Pet{//狗类,子类继承Pet的eat方法,并重写。以及添加一个word方法,测试向上转型和向下转型。
public void eat(){
System.out.println("我是一只狗,喜欢吃骨头1!!!!!!!!!!");
}
public void word(){
System.out.println("看门");
}
}

public class Cat extends Pet{//猫类 同上
public void eat(){
System.out.println("我是一只猫,吃鱼!!!!");
}
public void work(){
System.out.println("抓老鼠!!!!!");
}
}

public class Test {//测试类,

public void a(Pet pet){//测试向下转型(可以调用子类的方法)
if (pet instanceof Dog) {
Dog dog1 = (Dog) pet;
dog1.word();
}else if(pet instanceof Cat){
Cat cat1 = (Cat) pet;
cat1.work();
}
}
public void b(Pet pet){
pet.eat();
}
public static void main(String[] args) {
/*Pet pet = new Dog();//向上转型 是使用的父类的属性和方法,
// 但是子类对父类进行重写的方法可以调用,子类重新写的方法不能够调用
pet.eat();*/
Pet pet = new Pet();
Test t = new Test();
Dog dog = new Dog();
Cat cat = new Cat();
Pet pet1 = new Dog();//向上转型,只能使用父类存在的方法

pet1.eat();
pet.eat();
t.b(dog);
t.b(cat);
t.a(cat);
t.a(dog);
}

}