多态
文章目录
Java中为什么要有多态
Java中使用多态的主要目的是提高代码的可重用性和扩展性,使得代码更加灵活和易于维护。通过多态,我们可以将不同的对象看做是同一种类型,从而使得我们可以使用同一种接口来操作这些对象,而不必关心具体的实现细节。
一、多态的定义
多态是面向对象编程中的一个重要概念,它指的是同一个对象在不同情况下具有不同的表现形式和功能。在Java中,多态是指同一个类型的对象,在不同的情况下可以表现出不同的行为。
二、使用多态的前提条件
1.使用条件
1.必须在继承体系下,子类必须继承父类
2.子类必须要对父类中方法进行重写
3.通过父类的引用调用重写的方法 (对于重写不在此处介绍)
2.代码示例
class Animal {
public void sound() {
System.out.println("The animal makes a sound");
}
}
class Cat extends Animal {
public void sound() {
System.out.println("The cat meows");
}
}
class Dog extends Animal {
public void sound() {
System.out.println("The dog barks");
}
}
public class Main {
public static void main(String[] args) {
Animal myAnimal = new Animal();
Animal myCat = new Cat();
Animal myDog = new Dog();
myAnimal.sound();
myCat.sound();
myDog.sound();
}
}
在这个例子中,Animal是一个父类,而Cat和Dog是它的子类。在main方法中,我们创建了一个Animal对象,一个Cat对象和一个Dog对象。然后,我们通过调用它们的sound方法来展示不同的行为。由于myCat和myDog是Animal类型的引用,但是它们指向的是Cat和Dog对象,因此在调用sound方法时会表现出不同的行为,这就是多态的体现。
当代码运行时的结果是:
三、多态的两种形式–向上转型和向下转型
1.向上转型
a.代码示例
class Animal {
public void sound() {
System.out.println("The animal makes a sound");
}
}
class Cat extends Animal {
public void sound() {
System.out.println("The cat meows");
}
}
class Dog extends Animal {
public void sound() {
System.out.println("The dog barks");
}
}
public class Main {
public static void main(String[] args) {
Animal myAnimal = new Animal();
Animal myCat = new Cat();
Animal myDog = new Dog();
myAnimal.sound();
myCat.sound();
myDog.sound();
}
}
b.详细解释
Java中的向上转型是指一个子类对象赋值给一个父类类型的变量。这个过程是隐式的,不需要强制类型转换。
向上转型:实际就是创建一个子类对象,将其当作父类对象来用
//伪代码
语法格式:父类类型 对象名 = new 子类类型();
//例如上面的示例代码
Animal myAnimal = new Animal();
Animal myCat = new Cat();
Animal myDog = new Dog();
比如上面的代码。myAnimal 是父类类型,但是可以引用一个子类对象,因此从小范围向大范围的转换。
c.优缺点
1.优点:提高代码的灵活性和可扩展性
向上转型的主要作用是提高代码的灵活性和可扩展性。通过向上转型,我们可以将一个具体的子类对象看做是一个更为抽象的父类对象,从而使得我们可以使用更为通用的方法和接口来操作这些对象。这样,我们就可以在不改变原有代码的情况下,轻松地扩展程序的功能,增加新的子类对象。
2.缺点:可能会丢失子类特有的方法和属性
向上转型的缺点是可能会丢失子类特有的方法和属性。由于父类类型的变量不能访问子类特有的方法和属性,因此在进行向上转型时,这些方法和属性会被隐藏起来。如果我们需要使用这些特有的方法和属性,就需要进行向下转型。另外,由于向上转型是隐式的,因此可能会导致代码的可读性降低。
2.向下转型
a.代码示例
class Animal {
public void sound() {
System.out.println("The animal makes a sound");
}
}
class Cat extends Animal {
public void sound() {
System.out.println("The cat meows");
}
public void scratch() {
System.out.println("The cat scratches");
}
}
class Dog extends Animal {
public void sound() {
System.out.println("The dog barks");
}
public void fetch() {
System.out.println("The dog fetches");
}
}
public class Main {
public static void main(String[] args) {
Animal myAnimal = new Cat();
myAnimal.sound();
if (myAnimal instanceof Cat) {
Cat myCat = (Cat) myAnimal;
myCat.scratch();
}
}
}
在这个例子中,我们创建了一个Animal类型的变量myAnimal,并将其赋值为一个Cat对象。然后,我们调用myAnimal的sound方法,输出"the cat meows"。接着,我们使用instanceof运算符来检查myAnimal是否是Cat类型的对象。由于myAnimal指向的是一个Cat对象,因此instanceof运算符返回true。然后,我们使用强制类型转换将myAnimal转换为Cat类型的变量myCat,并调用它的scratch方法,输出"The cat scratches"。这就是多态的向下转型的体现。
b.详细解释
Java中的向下转型是指将一个父类类型的变量强制转换为一个子类类型的变量。向下转型需要进行强制类型转换,如果转换失败会抛出ClassCastException异常。
向下转型的实质是一个父类类型的变量强制转换为一个子类类型的变量
语法格式
public class Main {
public static void main(String[] args) {
Animal myAnimal = new Cat();
myAnimal.sound();
Cat myCat = (Cat) myAnimal;
}
}
但是向下转型也会带来问题,比如在下面的代码中
public class Main {
public static void main(String[] args) {
Animal myAnimal = new Cat();
Animal myAnimal1 = new Dog();
myAnimal.sound();
myAnimal1.sound();
Cat myCat = (Cat) myAnimal;
Cat myCat1 = (Cat) myAnimal1;
myCat.scratch();
myCat1.scratch();
}
}
当运行下面的代码的时候,程序可以通过编程,但是运行的时候就会报错
这是myAnimal1实际上指向的是狗,现在要强制还原成为猫,无法正常还原,所以运行时抛出异常ClassCastException
Java中为了提高向下转型的安全性,引入了 instanceof ,如果该表达式为true,则可以安全转换。
public class Main {
public static void main(String[] args) {
Animal myAnimal = new Cat();
myAnimal.sound();
if (myAnimal instanceof Cat) {
Cat myCat = (Cat) myAnimal;
myCat.scratch();
}
}
}
instanceof运算符是一种检查对象类型的运算符,它可以用来判断一个对象是否是某个类的实例。它的优点是可以避免类型转换异常,因为它可以在转换之前先判断对象类型是否正确。缺点是需要额外的代码来进行判断,从而可能会导致代码的复杂性增加。
c.优缺点
1.优点:可以获取子类独有的方法和属性
向下转型的优点是可以获取子类独有的方法和属性,从而可以对子类进行更为具体的操作。同时,向下转型可以使得程序更加灵活和可扩展,可以在不改变原有代码的情况下,增加新的子类对象。
2.缺点:可能会导致类型转换异常
向下转型的缺点是可能会导致类型转换异常,因为父类类型的变量并不一定都可以转换为子类类型的变量。另外,向下转型也会破坏程序的封装性,因为它可以直接访问子类的方法和属性,从而可能导致一些安全问题。
总结
多态可以提高代码的可重用性,扩展性和灵活性,但是代码的运行效率会降低,比属性没有多态性,当父类和子类都有同名属性的时候,通过父类引用时,只能调用父类自己的成员属性。