多态:(普通类的多态)
概述:同一对象在不同时刻表现出来的不同状态(形态)。
比如说:水,常温是液体,高温是气体,低温是固体。
前提:
1、要有继承关系。
2、要有方法重写。
3、要有父类引用指向子类对象。
Animal a = new Cat();
成员访问角度:
成员变量:
编译看左边(父类),运行看左边(父类)。
解释:
编译看左边:看的是左边(父类)有没有这个变量,有就编译通过,没有就报错。
运行看左边:实际运行,用的还是左边(父类)的成员变量。
成员方法:
非静态方法:(动态绑定)
编译看左边(父类),运行看右边(子类)。
解释:
编译看左边:看的是左边(父类)有没有这个成员方法,有就编译通过,没有就报错。
运行看右边:实际运行,用的是右边(子类)的成员方法。
静态方法:
编译看左边(父类),运行看左边(父类)。
解释:
编译看左边:看的是左边(父类)有没有这个静态方法,有就编译通过,没有就报错。
运行看左边:实际运行,用的还是左边(父类)的静态方法。
理解:
静态成员是属于类的,所以算不上重写。
总结:
只有非静态的方法,是编译看左边,运行看右边。原因是因为:方法有重写。
其他(静态方法,成员变量)都是编译看左边(父类),运行看左边(父类)。
向上和向下转型:
double d = 12; //隐式类型转换 小给大
int i = (int)d; //强制类型转换 大转小
Fu f = new Zi(); //小给大 向上转型
Zi z = (Zi)f; //大转小 向下转型
注意:
转型的时候可能会出一个异常:类名转换异常(ClassCastException)
原因是:类型不兼容(比如说:要把一个狗转成猫)
好处和弊端:
好处:
1、维护性。
2、扩展性。
3、可以作为方法形参的数据类型,用于接收其任意的子类对象。
public static void method(Animal a) { //Animal a = new Animal();
//Animal a = new Cat();
//Animal a = new Dog();
//Animal a = new Pig();
//里边放(调用)的一般是所有子类的共性内容。
a.eat();
a.sleep();
}
instanceof关键字:
格式: 引用 instanceof 数据类型
解释: 判断前边的引用 是否是 后边的数据类型。
弊端:
父类引用不能使用子类的特有成员。
抽象类的多态:
抽象类:有抽象方法的类。
抽象方法:没有方法体的方法就叫抽象方法,用abstract关键字修饰。
public abstract void show();
基本特点:
1、抽象类,抽象方法必须用关键字abstract修饰。
2、抽象类中不一定有抽象方法,但是有抽象方法的类一定是抽象类或者接口(接口不是类)。
3、抽象类不能被实例化。
//也就是说,抽象类不能创建该类对象。 Animal(抽象类) a = new Animal();这样写是错误的。
抽象类怎么实例化?
通过多态,创建其具体的子类对象,来完成实例化。
4、抽象类的子类:
A:要么也是抽象类。
B:要么重写抽象类中 所有的抽象方法。
成员特点:
成员变量:
可以是变量,也可以是常量。
构造方法:
有。
抽象类既然不能被实例化,要构造方法有什么用?
用于子类对象访问父类数据前,对父类数据进行初始化。
成员方法:
可以是抽象方法,也可以是非抽象方法。
抽象方法:强制要求子类必须完成某些事情。
非抽象方法:用于被子类继承,提高代码的复用性。
面试题:
题目1:一个抽象类如果没有抽象方法,可不可以定义为抽象类?如果可以,有什么意义?
可以,这么做的目的只有一个,就是不让其他的类来创建该类的对象。
题目2:abstract关键字不能和哪些关键字共存?
private:被private修饰的内容,子类是没有办法继承的,但是抽象方法是要求子类必须重写的,所以他们互相矛盾
final:被final修饰的内容,子类是没有办法重写的,但是抽象方法是要求子类必须重写的,所以他们互相矛盾
static:被static修饰的内容可以通过类名.的形式调用,但是我们知道抽象方法是没有方法体的,所以及时可以通过类名.的方式去调用,也是没有任何意义的,所以他们不能共存。
接口多态:
概述:比抽象类更抽象,里边所有的方法都是抽象的。
基本特点:
1、接口用关键字interface修饰。
2、类实现接口用关键字: implements
3、接口不能实例化。
怎么实例化?
通过多态,创建其具体的子类对象,来完成实例化。
4、接口的子类:
A:要么是抽象类(接口)。但是意义不大。
B:要么是具体类,但是必须重写接口中的所有抽象方法(推荐)。
成员特点:
成员变量:
只能是常量,因为有默认修饰符:public static final,
如果我们不写,系统会默认加上,推荐手动写上。
构造方法:
没有构造方法。
成员方法:
只能是抽象方法,因为有默认修饰符:public abstract
如果我们不写,系统会默认加上,推荐手动写上。
总结:接口中有且只有常量或者抽象方法。
类与接口的关系:
类与类:
继承。可以单继承,不能多继承,但是可以多层继承。
类与接口:
实现关系,可以单实现,也可以多实现,还可以在继承一个类的同时,实现多个接口。
接口与接口:
继承。可以单继承,也可以多继承。
抽象类和接口的区别:
1、成员区别
2、关系区别
3、设计理念的区别:
抽象类:被继承,体现的是is a的关系,里边定义的是整个继承体系的 共性内容。
接口:被实现,体现的是like a的关系,里边定义的是整个继承体系的 扩展内容。
* A:看下面程序是否有问题,如果没有,说出结果
*
class Fu {
public void show() {
System.out.println("fu show");
}
}
class Zi extends Fu {
public void show() {
System.out.println("zi show");
}
public void method() {
System.out.println("zi method");
}
}
class Test1Demo {
public static void main(String[] args) {
Fu f = new Zi();
f.method();
f.show();
}
}
* B:看下面程序是否有问题,如果没有,说出结果
*
class A {
public void show() {
show2();
}
public void show2() {
System.out.println("我");
}
}
class B extends A {
public void show() {
show2();
}
public void show2() {
System.out.println("爱");
}
}
class C extends B {
public void show() {
super.show(); //在这里调用了父类的show()方法,这里调用的是show2()
}
public void show2() {
System.out.println("你");
}
}
public class Test2DuoTai {
public static void main(String[] args) {
A a = new B(); //多态
a.show(); //编译看左,运行看右。 //"爱"
B b = new C(); //多态
b.show(); //编译看左,运行看右。 "你"
}
}
中午作业:
1、写代码实现以及理解一下两句话。
第一个话述:
总结:
只有非静态的方法,是编译看左边,运行看右边。原因是因为:方法有重写。
其他(静态方法,成员变量)都是编译看左边(父类),运行看左边(父类)。
第二个话述:多态的好处
3、可以作为方法形参的数据类型,用于接收其任意的子类对象。
public static void method(Animal a) {
//里边放(调用)的一般是所有子类的共性内容。
a.eat();
a.sleep();
}
|
|