多态,是指把类中具有相似功能的不同方法使用同一个方法名来实现,从而可以使用相同的方式来调用这些具有不同功能的同名方法。
多态实现的前提是:
(1)继承、重写与父类指针指向子类对象。
(2)方法重载
多态的特点:具有灵活、抽象、行为共享、代码共享的优势,很好地解决了应用程序方法同名问题。
多态,简而言之就是同一个行为具有多个不同表现形式或形态的能力。
public class Bike {
String name = "JAVA";
public void sport() {
System.out.println("我叫"+name+",我比轮子更快");
}
}
public class Wheel extends Bike{
String name = "KenDa";
public void sport() {
System.out.println("我叫"+name+"我滚得快");
}
public void run() {
System.out.println("时速不高于1公里每小时");
}
}
测试类
public class Demo_01 {
public static void main (String[] args) {
Bike bike = new Wheel(); //父类引用指向子类对象,轮子提升为自行车
//父类引用子类就是向上转型
System.out.println(bike.name);
bike.sport();
}
}
运行结果如下图
从图中运行得结果可以得出,数字1的结果是Bike类中的一个局部变量值,而数字2是由于父类引用指向了子类对象,调用了该类中的sport()方法后得出此结果。
public class Demo_01 {
public static void main (String[] args) {
Bike bike = new Wheel(); //父类引用指向子类对象,轮子提升为自行车
//父类引用子类就是向上转型
System.out.println(bike.name);
bike.sport();
Wheel wheel =(Wheel)bike; //向下转型
wheel.sport();
wheel.run();
}
}
运行结果如下图
从图中运行得结果可以得出,数字4的结果是向下转型后得出的结果。
好处是:
a:提高了代码的维护性(继承保证)
b:提高了代码的扩展性(由多态保证)
弊端是:
不能使用子类的特有属性和行为
public class Animal {
public void eat() {
System.out.println("动物吃饭");
}
}
public class Cat extends Animal {
public void eat() {
System.out.println("猫吃鱼");
}
public void catchMouse() {
System.out.println("猫抓老鼠");
}
}
测试类
public class Deno {
public static void main(String[] args) {
method(new Cat());
}
public static void method(Cat t) {
t.eat();
}
}
运行结果没有问题,在加一个Dog类就出事了
public class Dog extends Animal{
public void eat() {
System.out.println("狗吃肉");
}
public void lookHome() {
System.out.println("狗看家");
}
}
测试类
public class Deno {
public static void main(String[] args) {
method(new Cat());
method(new Dog()); //此语句不成立
}
public static void method(Cat t) {
t.eat();
}
}
主要意思在说没有合适的方法提供给Dog类,解决方法加一个同Cat一样的方法就好了,如下图
public class Deno {
public static void main(String[] args) {
method(new Cat());
method(new Dog()); //此语句成立
}
public static void method(Cat t) {
t.eat();
}
public static void method(Dog t) { //提供Dog类参数
t.eat();
}
}
> >问题思考:但如果出现很多很多子类怎么办?像这样一个一个地添加方法,工作效率大大降低。 因此,向上和向下转型就很有必要了。
第一种注意
public class Deno {
public static void main(String[] args) {
method(new Cat());
method(new Dog());
//Animal a = new Cat();
//开发的时候很少在创建对象的时候 用父类引用指向子类对象,
//直接创建子类对象更方便,可以使用子类中的特有属性
}
public static void method(Animal a) { //当作参数的时候用多态最好,因为扩展性强
a.eat();
a.catchMouse(); //此语句报错,原因为Animal类中没有此方法,也不可能定义该方法
}
}
第二种注意
public class Deno {
public static void main(String[] args) {
method(new Cat());
method(new Dog());
}
//如果把狗转换成猫就会出现类型转换异常,ClassCastException
public static void method(Animal a) { //当作参数的时候用多态最好,因为扩展性强
Cat c = (Cat) a; //采用向下转型
c.eat();
c.catchMouse();
}
}
最终解决方案,使用关键字 instanceof
public class Deno {
public static void main(String[] args) {
method(new Cat());
method(new Dog());
}
public static void method(Animal a) { //当作参数的时候用多态最好,因为扩展性强
//关键字 instanceof 判断前边的引用是否是后面的数据类型
if(a instanceof Cat) {
Cat c = (Cat) a;
c.eat();
c.catchMouse();
}else if(a instanceof Dog) {
Dog d = (Dog) a;
d.eat();
d.lookHome();
}else {
a.eat();
}
}
}
生命如旅行,不求速达终点,贵就是在过程精彩。