多态
->1.多态概念
->2.类型转换(upcasting&downcasting)
->3.动态绑定
->4.抽象类
->5.实例讲解
1.多态概念:
- 多态(Polymorphism)按字面的意思就是“多种状态”。在面向对象语言中,接口的多种不同的实现方式即为多态。多态性是允许你将父对象设置成为一个或更多的他的子对象相等的技术,赋值之后,父对象就可以根据当前赋值给它的子对象的特性以不同的方式运作。简单的说,就是一句话:允许将子类类型的指针赋值给父类类型的指针。
父类型变量可以引用子类型的对象,父类型对象访问派生类重写的方法。
多态概括来说涉及两个运用方面:*循环调用基类对象,访问不同派生类方法
*实参是派生类;形参是基类
2.多态存在的三个必要条件:
- 继承;
- 重写;
- 向上转型;
2.类型转换(upcasting&downcasting)
(1).向上转型(upcasting)
Object a=new Circle();
此语句将对象new Circle()赋值给一个Object类型的参数a。因为Circle类是Object类的子类,所以Circle类型的实例也是Object类型的实例,上述语句是合法的,将这种转换成为upcasting。向上转型特点:
1.不需要强制转型;
2.父类引用指向的或者调用的方法为子类的方法(动态绑定);
3.向上转型只能调用子类重写的方法,子类自己的方法不能调用。
(2).向下转型(downcasting)
Circle b=a;(此语句编译失败,因为Object对象不一定是Circle的实例)
Circle b=(Circle)a;(使用显示转换,声明a是一个Circle对象)
Q:如何判断一个父类型的对象是不是子类型的实例呢?
A:引入instanceof操作符实现
If(a instanceof Circle){
//判断Object类型的a是否为Circle的实例
System.out.println((Circle)a.getArea());
}
3.动态绑定:
方法可以在沿着继承链的多个类中实现。方法可以在父类中定义,而在子类中重写。
思考代码:
Object a=new circle();
- toString();
两个术语:声明类型、实际类型
声明类型:变量的这个类型为声明类型,这里a的声明类型为Object;
实际类型:示例可以使用声明类型(父类型)或它的子类型的构造方法创建,变量引用的对象的实际类为实际类型。这里a的实际类为circle。
Q:这里的a调用的是哪一个toString()呢?
A:a调用方法由a的实际类型决定。这称为动态绑定。
下面示例解释动态绑定:
pubic static void main(String[] args){
m(new GraduateStudent());
m(new Student());
m(new Person());
m(new Object());
}
public static void m(Object x){
System.out.println(x.toString());
}
class GraduateStudent extends Student{}
class Student extends Person{
@Override
public String toString(){
return "Student";
}
}
class Person extends Ojbect{
@Override
public String toString(){
return "Person";
}
}
方法m有一个object参数,而person、student、GraduateStudent延继承链均为object的子类,所以执行m(object x)方法时,x可能是GraduateStudent、Student、Person或者Object的实例,类toString()在Student、Person、Object中均有自己的实现方法,使用哪个实现取决于x的实际类型。如m( new GraduateStudent())会调用其父类Student中的toString方法。
4.抽象类
1.思考:从软件设计人员的角度来看,作为矩形和圆形等具体形状类的共同父类,图形类表示的是一种抽象的概念,既不应该允许下层的代码人员创建出Geometry类的具体实例——常规的类不能满足此要求;
2.解决办法:通过abstract关键字将getArea方法修饰为抽象的,此时的方法称为抽象方法。
抽象方法事出现在基类的一种方法,但要求在派生类中被重写。
3.格式:一个抽象方法只有方法头,没有方法主体
访问修饰符 abstract 返回类型 方法名(参数列表);
4.抽象方法:
包含抽象方法的类会自动变成抽象类,因此必须以abstract 关键字声明。
Public abstract class 类名
5.例子
abstract class B //创建抽象类B{
private String str; //私有成员变量str
public B(String a) //抽象类的构造函数{
this.str=a;
}
public abstract void play(); //抽象类中的play()抽象方法
}
public class A extends B //A类继承抽象类B {
public A(String a) //A的构造函数{
super(a);
}
@Override //覆盖父类B中的play()
public void play(){
System.out.println("重写抽象类中的play方法");
}
}
5.实例讲解
(1)引入一个较为典型的例子
public class animal{
public static void main(String[] args) {
animals c=new cat();
animals d=new dog();
c.say();
d.say();
}
}
abstract class animals {
public abstract void say();
}
class cat extends animals{
@Override
public void say() {
System.out.println("喵喵喵");
}
}
class dog extends animals{
@Override
public void say() {
System.out.println("汪汪汪");
}
}
此实例中,运用到了abstract抽象类,在基类animals中定义say方法,在子类cat和dog中重写这个方法,在主类声明中,向上转换并调用say方法。
(2)
public class demo04 {
public static void main(String[] args) {
People p=new Stu();
p.eat();
//调用特有的方法
Stu s=(Stu)p;
s.study();
//((Stu) p).study();
}
}
class People{
public void eat(){
System.out.println("吃饭");
}
}
class Stu extends People{
@Override
public void eat(){
System.out.println("吃水煮肉片");
}
public void study(){
System.out.println("好好学习");
}
}
class Teachers extends People{
@Override
public void eat(){
System.out.println("吃樱桃");
}
public void teach(){
System.out.println("认真授课");
}
}
输出:吃水煮肉片
好好学习
2.循环调用基类对象
可以通过多态实现不同类的同一(重写)方法的调用,可以增强代码的可读性。
public class Money {
public static void main(String[] args) {
changemoney[] list=new changemoney[3];
list[0]=new rmb(100);
list[1]=new dollar(100);
list[2]=new pound(100);
for(int i=0;i<3;i++) {
System.out.println(list[i].setmoney());
}
}
}
class changemoney{
private double money;
public changemoney() {
}
public changemoney(double newrmb) {
this.money=newrmb;
}
public double setmoney() {
return money;
}
}
class rmb extends changemoney{
private double rmb;
public rmb(double newrmb) {
rmb=newrmb;
}
@Override
public double setmoney() {
return rmb;
}
}
class dollar extends changemoney{
private double dollar;
public dollar(double newdollar) {
dollar=newdollar;
}
@Override
public double setmoney() {
return dollar/6.55;
}
}
class pound extends changemoney{
private double pound;
public pound(double newpound) {
pound=newpound;
}
@Override
public double setmoney() {
return pound/8.2464;
}
}
//使用循环实现输出。
输出:100.0
15.26715572519085
12.126503686457122 //输出rmb、dollar、pound
3.实参是派生类;形参是基类
public class CastingDemo{
public static void main(String[] args){
Object object1=new Circle(1);
Object object2=new Rectangle(1,1);
displayObject(object1);
displayObject(object2);
public static void displayObject(Object object){
if(object instanceof Circle){
System.out.println("The circle area is"+((Circle)object).getArea());
}
else if(object instanceof Rectangle){
System.out.println("The rectangle area is"+((Rectangle)object).getArea());
}
}
}
}