1.知识点的过渡
1.1继承:
继承是建立在子类和父类的基础之上的
类之间的继承—单继承
接口之间的继承—多继承
类与接口之间的关系—一对多—实现关系:一个类实现多个接口
1.2基于以上的知识:
1.按照封装的高度来说—-接口(高)—>抽象类—>普通类
2.接口也是一个特殊的类,其实也是父类
3.如果一个子类与父类产生了关系—继承关系:从类型上来说子类属于父类的一个实例
1.3新知识:
如果说父类的引用指向子类的对象就是—-向上造型
对象的多态性,只适用于方法(编译看左边,运行看右边),不适用于属性(编译和运行都看左边)
多态的前提必须有子父类关系,或者实现接口关系
2.向上造型:是多态的一种实现
2.1向上造型
父类(接口)的引用可以指向子类的对象,展现出来的是父类(接口)的功能
- 子类的引用变量可以指向子类的对象,展现出来的是子类的功能
- 子类对象可以展现出多种形态,这多种形态叫做多态—多态后不能再调用子类特有的方法
- 格式:
- 父类类型 变量名=new 子类的对象();
- 变量名.方法名
- 当多态出现以后,编译期只能调用父类中声明的方法,但是在运行期实际执行的是子类重写父类的方法
多态的使用场景:
1.为变量赋值的时候使用多态,达到父类的引用子类的对象,直接为变量赋值
- 2.调用方法的时候,为方法的参数进行赋值
- 3.方法的返回值,可以定义为父类的类型,但是返回的是子类的对象。
- 当该方法被调用后,用父类的类型接收 ```java package duotai_01;
/**
- @author Lynn
- @create 2020-12-01-15:15 */
/**
- 父类—动物类 *
- 用于展示多态的抽象方法
吃饭,睡觉 */ public abstract class Animal { //普通方法 public void eat(){
System.out.println("吃饭");
}
//抽象方法 public abstract void sleep(); }
/**
- @author Lynn
- @create 2020-12-01-15:17 */
/**
- 人类—子类(具体类) *
- 用于展示多态的实现
在父类的共性功能外,有自己学习,工作的方法 */ public class Person extends Animal{ @Override public void sleep() {
System.out.println("睡在床上");
}
//拓展子类自己的方法 public void study(){
System.out.println("学习使我快乐");
}
//工作的方法 public void work(){
System.out.println("工作可以创造金钱");
}
//重写父类中的方法 @Override public void eat(){
System.out.println("吃饱饭踏实");
} }
/**
- @author Lynn
@create 2020-12-01-15:53 */ public class Dog extends Animal{ @Override public void sleep() {
System.out.println("睡在地上");
}
public void kanmen(){
System.out.println("千里无极");
}
@Override public void eat(){
System.out.println("吃骨头");
} }
/**
- @author Lynn
- @create 2020-12-01-15:22 */
import java.security.PublicKey;
/**
- 演示向上造型 *
- 其实向上造型是多态的一种实现方式
- 父类(接口)的引用可以指向子类的对象,展现出来的是父类(接口)的功能
- 子类的引用变量可以指向子类的对象,展现出来的是子类的功能
- 子类对象可以展现出多态的实现 *
- 格式:
- 父类类型 变量名=new 子类的对象();
- 变量名.方法名 *
- 当多态出现以后,调用的方法是子类重写后的方法 *
- 多态的使用场景:
- 1.为变量赋值的时候使用多态,达到父类的引用子类的对象,直接为变量赋值
- 2.调用方法的时候,为方法的参数进行赋值
- 3.方法的返回值,可以定义为父类的类型,但是返回的是子类的对象。
当该方法被调用后,用父类的类型接收 */ public class SubClassType { public static void main(String[] args) {
//创建子类对象
Person p=new Person();
p.eat();
p.sleep();
p.work();
p.study();
System.out.println("-------------------------");
//使用向上造型--展现出来的是父类中的功能
Animal a=new Person();
//调用的是父类中的方法,结果是子类中重写后的方法
a.eat();//吃饱饭踏实
a.sleep();//睡在床上
// a.work();//调用不到
System.out.println("-------------------------------");
//调用feed方法
feed(new Person());//传一个Animal的子类对象
feed(new Dog());//传一个Animal的子类对象
// feed(new Animal() //Animal是一个抽象类不能被实例化
}
//封装一个方法,用于灵活地调用所有的方法---传入参数是一个父类
public static void feed(Animal a){//a是Animal的引用,可以接收Animal中所有的子类对象
//调用该动物吃饭的方法
System.out.println("feed方法内");
a.eat();
}
}
<a name="RpARI"></a>
### 2.2重点补充:
1.方法的重载和重写的区别<br />方法的重载看到的是引用;<br />方法的重写看的是对象
2.方法的重载时在编译期绑定参数的--编译期就是按下保存键按钮之后jvm检查java代码的语法的时候<br />方法的重写实在运行期执行的--因为**对象实在运行期才出现的**
<a name="3."></a>
# 3.向下造型
<a name="j6qXf"></a>
### 多态的实现:
- 1.向上造型(向上转型):**多态本身就是子类类型向父类类型的转换** - 默认
- 格式:父类类型 变量名 = new 子类对象();
2.向下转型:一个已经向上转型的子类对象可以**使用强制类型转换**的格式,将父类引用转为子类引用
- 格式:子类类型 变量名 = (子类类型)变量名;
**注意:**<br />在强制类型转换的时候,必须是什么对象就转换为什么对象!<br />如果使用错误,使用了其他类型的对象,那么编译期不会报错,但是在运行期会报错(造型异常)<br />java.ClassCastException--表示**造型异常**
```java
package duotai_02;
/**
* @author Lynn
* @create 2020-12-01-15:22
*/
/**
* 演示向下造型
*
* 其实向下造型是多态的一种实现方式
* 多态的实现:
* 1.向上造型(向上转型):多态本身就是子类类型向父类类型的转换 - 默认
* 格式:父类类型 变量名 = new 子类对象();
* 2.向下转型:使用起那个值类型转换
* 格式:子类类型 变量名 = (子类类型)变量名;
*
*
*/
public class SubClassType {
public static void main(String[] args) {
//创建子类对象
Person p=new Person();
p.eat();
p.sleep();
p.work();
p.study();
System.out.println("-------------------------");
//使用向上造型--展现出来的是父类中的功能
Animal a=new Person();
//调用的是父类中的方法,结果是子类中重写后的方法
a.eat();//吃饱饭踏实
a.sleep();//吃饱饭踏实
// a.work();//调用不到
System.out.println("------------向下转型-----------------");
Animal a1=new Dog();//向上造型
/*Person p1=(Person)a1;//向下转型---强制类型转换--
//造型异常(把狗造成人,不通)--对象在运行期产生的
p1.eat();
p1.sleep();*/
//正确的向下转型---注意类型
Dog d1=(Dog)a1;
d1.eat();//吃骨头
d1.sleep();//睡在地上
/**
* 在强制类型转换的时候,必须是什么对象就转换为什么对象!
* 如果使用错误,使用了其他类型的对象,那么编译期不会报错,但是在运行期会报错(造型异常)
* java.ClassCastException--表示造型异常
*/
/* System.out.println("-------------拓展------------------");
//调用feed方法
feed(new Person());//传一个Animal的子类对象
feed(new Dog());//传一个Animal的子类对象
// feed(new Animal() //Animal是一个抽象类不能被实例化*/
}
/*//封装一个方法,用于灵活地调用所有的方法---传入参数是一个父类
public static void feed(Animal a){//a是Animal的引用,可以接收Animal中所有的子类对象
//调用该动物吃饭的方法
System.out.println("feed方法内");
a.eat();
}*/
}
解决造型异常的方案:
使用一个instanceof关键字来判断某个对象是不是属于某种类型
最后会返回true或false,进行了对象的判断后就可以保证
使用格式:
boolean b = 对象 instanceof 数据类型;
如
Person p1 = new Student(); // 前提条件,学生类已经继承了人类
boolean flag = p1 instanceof Student; //flag结果为true
boolean flag2 = p2 instanceof Teacher; //flag结果为false
public class SubClassType {
public static void main(String[] args) {
System.out.println("------------向下转型-----------------");
//狗
Animal a1=new Dog();
method(a1);
//人
Animal a2=new Person();
method(a2);
}
//封装一个方法用于判断这个类型
public static void method(Animal a){
//如果是狗,就看门,如果是人就学习工作
if(a instanceof Dog){
//强制转换成狗
Dog d=(Dog)a;
d.kanmen();
}
if(a instanceof Person){
//强制转换成人
Person p=(Person)a;
p.study();
p.work();
}
}
}
多态的好处:
- 大大提高了程序的扩展性
- 提高了程序的复用性