一、面向对象特征之三:多态性
1、多态性:父类的引用指向子类对象;
Person p1=new Man(); 多态
(父类) (子类)
容量小 容量大
相当于double 相当于int
如上总结归纳:多态性中,创建实体后,不能调用子类中存在而父类中不存在的方法。调用的方法必须是子类重写父类的方法。
2、面向对象的第三个特性:多态性;
2-1、多态性指的是什么?
多态性可理解为一个事物的多种表现形式。
1)、方法的重载与重写; 2)、子类对象的多态性
2-2、子类对象多态性使用的前提:(1)、要有类的继承;(2)、要有子类对父类方法的重写
3、程序运行分为编译状态和运行状态:
(1)、对于多态性来说,编译时,"看左边",将此引用变量理解为父类的类型
(2)、运行时,"看右边",关注于真正对象的实体,子类的对象。那么执行的方法就是子类重写父类的方法。
(在多态性中,创建实体后,不能调用子类中存在而父类中不存在的方法。必须调用的是子类重写父类的方法。)
子类对象的多态性只适用于方法,不适用于属性。
(如:Person类中定义了一个int型的id为1002;person的子类Man中也定义了int型的id为1002;在测试类中main方法中有语句:Person p1=new Man(); System.out.println(p1.id); 此返回值为输出1002;因为多态针对的是对象,类中的属性不可以多态。)
当多态语句 Person p1=new Man(); 之后要调用p1.属性,无论什么情况调用的都是多态语句赋值号左边的类中的对应属性。
4、上转型与下转型:
4-1、向上转型:制造的子类对象赋给父类;
4-2如下面的程序实例:如果希望p1和p2可以调用see()方法,需要向下转型(类似C语言的强制类型转换)。
Person p2=new Woman();
p2.eat(); p2.walk();
// p2.see(); 不能调用(因为see()方法是子类Woman特有的,在父类中不存在。)
Woman w1=(Woman)p2; //向下转型(类似于C语言的强转)
图解:
- instanceof关键字:
格式: 对象a instanceof 类A
解释:判断对象a是否是类A的一个实例。是的话返回true;否则false。
实例演示:
if(p1 instanceof Woman) { //判断p1是否是一个Woman类型。
Woman w2=(Woman)p1; //如果p1是Woman类型则用Woman强转
w2.see();
}
6、有多态情况下的参数为父类类型的参数传递问题:
Public void show(Person p){ }
没有多态的话调用show()方法时,传参数只能传递Person类型的;而有了多态后,可以传递Person类型的子类的参数。即形参列表中可以传递Person类的参数或Person类的子类的参数。
如果没有多态性
public void show(Person p) { }
public void show(Woman w) { }
public void show(Man m) { }
以上这三个调用会有各自的形参传递;
但有了多态性后一个带有Person类型形参的就可以实现以上三个,因为Woman和Man都是Person类的子类。
二、代码实例解析:
1、Person类(父类):
package com.atguigu.duotai;
public class Person {
private String name;
private int age;
//有参的构造方法
public Person(String name, int age) {
super();
this.name = name;
this.age = age;
}
public Person() { //无参的构造方法
super();
}
public String getName() {
return name;
}
public void setName(String name) {
this.name = name;
}
public int getAge() {
return age;
}
public void setAge(int age) {
this.age = age;
}
//自定义的函数
public void walk() {
System.out.println("人走路");
}
public void eat() {
System.out.println("人吃饭");
}
}
2、Woman类(第一个子类):
package com.atguigu.duotai;
public class Woman extends Person{
private boolean isBeauty;
//getters和setters方法
public boolean isBeauty() {
return isBeauty;
}
public void setBeauty(boolean isBeauty) {
this.isBeauty = isBeauty;
}
public Woman() {
super();
}
public Woman(boolean isBeauty) {
super();
this.isBeauty = isBeauty;
}
//重写自定义方法
public void walk() {
System.out.println("女窈窕的走路");
}
public void eat() {
System.out.println("小口吃饭");
}
public void see() {
System.out.println(this.getName()+"今年"+this.getAge()+"岁了");
}
}
3、Man类(第二个子类):
package com.atguigu.duotai;
public class Man extends Person{
private boolean smoking;
public boolean Smoking() {
return smoking;
}
public void setSmoking(boolean smoking) {
this.smoking = smoking;
}
//有参的构造方法
public Man( boolean smoking) {
super();
this.smoking = smoking;
}
//无参的构造方法
public Man() {
super();
}
//重写从父类继承的方法;
public void walk() {
System.out.println("男儿走路,不低头");
}
public void eat() {
System.out.println("男-大口吃饭");
}
public void see() {
System.out.println(this.getName()+"看到了很多健身器材");
}
}
4、TestPerson类(测试类):
package com.atguigu.duotai;
/*
* 面向对象的第三个特性:多态性;
* 1、多态性指的是什么?
* 多态性可理解为一个事物的多种表现形式。
* 1)、方法的重载与重写; 2)、子类对象的多态性
* 2、子类对象多态性使用的前提:(1)、要有类的继承;(2)、要有子类对父类方法的重写
* 3、程序运行分为编译状态和运行状态
* 对于多态性来说,编译时,"看左边",将此引用变量理解为父类的类型
* 运行时,"看右边",关注于真正对象的实体,子类的对象。那么执行的方法就是子类重写父类的方法。
* (在多态性中,创建实体后,不能调用子类中存在而父类中不存在的方法。必须调用的是子类重写父类的方法。)
* */
public class TestPerson {
public static void main(String[] args) {
Person p=new Person();
p.eat();
p.walk();
Man m=new Man();
m.eat();
m.walk();
System.out.println("**********");
// new Man().eat(); 也可以运行出结果
// new Man().walk();
//子类对象的多态性:父类的引用指向子类对象
Person p1=new Man(); //向上转型
p1.eat(); p1.walk(); //以左为虚拟方法调用,
// 通过父类的引用指向子类的对象实体,
// 当调用方法时实际执行的必须是子类重写父类的方法;
// 不可以调用子类中存在而父类中没有的方法
// p1.see(); 不能调用(因为see()方法是子类Man特有的,在父类中不存在。)
Person p2=new Woman(); //
p2.eat(); p2.walk();
// p2.see(); 不能调用(因为see()方法是子类Woman特有的,在父类中不存在。)
Woman w1=(Woman)p2; //向下转型(类似于C语言的强转),使用强转符。
w1.see(); //强转后就可以调用see()方法了
// /*
// * 错误:java.lang.ClassCastException
// * */
// Woman w2=(Woman)p1; 不可以将Man类型强转为Woman类型,因为二者都是Person的子类。
// w2.see();
// Woman w2=(Woman)new Man();
//instanceof:
// 格式: 对象a instanceof 类A 解释:判断对象a是否是类A的一个实例。是的话返回true;否则false。
if(p1 instanceof Woman) { //判断p1是否是一个Woman类型。
Woman w2=(Woman)p1; //如果p1是Woman类型则用Woman强转
w2.see();
}
if(p1 instanceof Man) { //判断p1是否是一个Man类型的。
Man m1=(Man)p1; //如果p1是Man类型的则强转。
m1.see();
}
if(p1 instanceof Person) {
System.out.println("Hello world!");
}
}
}
运行结果如下:
人吃饭
人走路
男-大口吃饭
男儿走路,不低头
**********
男-大口吃饭
男儿走路,不低头
小口吃饭
女窈窕的走路
null今年0岁了
null看到了很多健身器材
Hello world!
三、多态性的一个使用:
package com.atguigu.duotai;
//多态使用的一个类子
public class TestAnimal {
public static void main(String[] args) {
TestAnimal t=new TestAnimal();
t.func(new Animal());
t.func(new Dog()); //因为有了多态性所以形参内用Animal的子类也行。
t.func(new Cat());
}
public void func(Animal a) {//包括了:(1)、public void func(Dog a) { } 和public void func(Cat a) { }
a.eat();
a.jump();
//还可以用强转
if(a instanceof Dog) {
Dog d=(Dog)a;
((Dog) a).say();
// d.say(); 二者结果相同;
}
if(a instanceof Cat) {
Cat c=(Cat)a;
((Cat) a).catchMouse();
// c.catchMouse();
}
}
}
class Animal{
String name;
int age;
public void eat() {
System.out.println("进食");
}
public void jump() {
System.out.println("Jump");
}
}
class Dog extends Animal{
public void eat() {
System.out.println("吃狗食");
}
public void jump() {
System.out.println("Dog Jump");
}
public void say() {
System.out.println("汪汪");
}
}
class Cat extends Animal{
public void eat() {
System.out.println("吃猫食");
}
public void jump() {
System.out.println("Cat Jump");
}
public void catchMouse() {
System.out.println("猫抓鱼");
}
}
四、多态的使用练习1:
结果如下所示:
四、多态的使用练习2:
1、GeometricObject类(父类):
package com.atguigu.duotai.test;
public class GeometricObject {
protected String color;
protected double weigth;
public GeometricObject(String color, double weigth) {
super();
this.color = color;
this.weigth = weigth;
}
public String getColor() {
return color;
}
public void setColor(String color) {
this.color = color;
}
public double getWeigth() {
return weigth;
}
public void setWeigth(double weigth) {
this.weigth = weigth;
}
public double findArea() {
return 0.0;
}
}
2、Circle类(GeometricObject类的第一个子类):
package com.atguigu.duotai.test;
public class Circle extends GeometricObject{ //报错,Circle有一个默认空参的,而GeometricObject没有。
private double radius;
public double getRadius() {
return radius;
}
public void setRadius(double radius) {
this.radius = radius;
}
public Circle(String color, double weigth, double radius) {
super(color, weigth);
this.radius = radius;
}
public double findArea() {
return Math.PI*radius*radius;
}
}
3、MyRectangle(GeometricObject类的第二个子类):
package com.atguigu.duotai.test;
public class MyRectangle extends GeometricObject{
private double width;
private double height;
public MyRectangle(String color, double weigth, double width, double height) {
super(color, weigth);
this.width = width;
this.height = height;
}
public double getWidth() {
return width;
}
public void setWidth(double width) {
this.width = width;
}
public double getHeight() {
return height;
}
public void setHeight(double height) {
this.height = height;
}
public double findArea() {
return width*height;
}
}
4、TestGeometric(测试类):
package com.atguigu.duotai.test;
public class TestGeometric {
public static void main(String[] args) {
TestGeometric t=new TestGeometric();
Circle c1=new Circle("Green",2.3,1.0);
Circle c2=new Circle("Red",2.3,1.0);
MyRectangle m1=new MyRectangle("blue",2.3,3.0,2.0);
t.displayGemoetricObject(c2);
boolean b=t.equalsArea(c1, c2);
System.out.println(b);
}
//判断两个对象的面积是否相等
public boolean equalsArea(GeometricObject o1,GeometricObject o2) {
// if(o1.findArea()==o2.findArea())
// return true;
// else
// return false;
return o1.findArea()==o2.findArea();
}
public void displayGemoetricObject(GeometricObject o) {
System.out.println(o.findArea());
}
}
错误整理:
1、
出现上图所示错误,原因是:SavingAccount类继承父类Account,父类Account类中为书写无参的构造方法。导致此类错误发生。