【学习笔记】多态
即同一方法可以根据发送对象的不同而采用多种不同的行为方式
一个对象的实际类型是确定的,但可以指向的引用类型有很多(一般指父类和有关系的类)
一个对象的实际类型是确定的
new Student();
new Person();
可以指向的引用类型就不确定了
Student s1 = new Student();
Person s2 = new Student(); //父类的引用指向子类的类型
Object s3 = new Student();
父类:
package com.oop.demo05;
public class Person {
public void run(){
System.out.println("father");
}
}
子类:
package com.oop.demo05;
public class Student extends Person{
}
测试类:
package com.oop;
import com.oop.demo05.Person;
import com.oop.demo05.Student;
public class Application {
public static void main(String[] args) {
Person s1 = new Student();
s1.run();
}
}
我们可以看到,虽然我们new的是Student,但是依然可以运行出父类的方法,原因是子类继承了父类的全部方法。
如果我们在子类中重写一下该方法
package com.oop.demo05;
public class Student extends Person{
@Override
public void run() {
System.out.println("son");
}
}
在测试类中调用一下,
package com.oop;
import com.oop.demo05.Person;
import com.oop.demo05.Student;
public class Application {
public static void main(String[] args) {
Person s1 = new Student();
Student s2 = new Student();
s1.run();
s2.run();
}
}
我们发现,两个结果都运行出了“son”,原因是,子类一旦重写了父类的方法,就会执行子类的方法
如果在子类中写一个子类独有的方法,父类引用类型的那个变量(s1)就不能调用子类独有的方法
public void eat(){
System.out.println("eat");
}
原因是s1的类型是Person ,Person 中是没有eat方法的,所以调用不了
如果在父类和子类中都有该方法的话,只要子类没有重写父类,那么就调用父类的,子类重写了父类,那么就调用子类的
总结一句话,对象能执行哪些方法,主要看对象左边的类型,和右边关系不大
Person s1 = new Student();
Student s2 = new Student();
Student(子类) 能调用的方法都是自己或继承父类的
Person(父类) 可以指向子类,但是不能调用子类独有的方法
多态的注意事项:
1.多态是方法的多态,属性没有多态
2.父类和子类有联系,如果类型不相同,却依旧转换的话,就会报类型转换异常 ClassCastException
3.多态存在的条件: 存在继承关系,方法需要重写,
父类的引用指向子类对象 Father f1 = new Son()
4.有些方法不能重写:
(1)static方法,它属于类,不属于实例
(2)final 常量
(3)private 方法
instanceof关键字
测试它左边的对象是否是它右边的类的实例,返回 boolean 的数据类型,存在继承关系则返回true,不存在继承关系则返回false
package com.oop;
import com.oop.demo05.Person;
import com.oop.demo05.Student;
import com.oop.demo05.Teacher;
public class Application {
public static void main(String[] args) {
//Object > Person > Student
//Object > Person > Teacher
Object o = new Student();
System.out.println(o instanceof Object); //true 它是Student父类的父类
System.out.println(o instanceof Person); //true 它是Student的父类
System.out.println(o instanceof Student); //true 它本身就是Student类
System.out.println(o instanceof Teacher); //false 它与Student都继承Person类,但是它们没有关系
System.out.println(o instanceof String); //false 它继承于Object ,与Student无关
}
}
package com.oop;
import com.oop.demo05.Person;
import com.oop.demo05.Student;
import com.oop.demo05.Teacher;
public class Application {
public static void main(String[] args) {
//Object > Person > Student
//Object > Person > Teacher
Object o = new Student();
System.out.println(o instanceof Object); //true 它是Student父类的父类
System.out.println(o instanceof Person); //true 它是Student的父类
System.out.println(o instanceof Student); //true 它本身就是Student类
System.out.println(o instanceof Teacher); //false 它与Student都继承Person类,但是它们没有关系
System.out.println(o instanceof String); //false 它继承于Object ,与Student无关
System.out.println("=================================");
Person person = new Student();
System.out.println(person instanceof Object); //true 它是Student父类的父类
System.out.println(person instanceof Person); //true 它是Student的父类
System.out.println(person instanceof Student); //true 它本身就是Student类
System.out.println(person instanceof Teacher); //false 它与Student都继承Person类,但是它们没有关系
//System.out.println(person instanceof String); //编译错误
System.out.println("=================================");
Student student = new Student();
System.out.println(student instanceof Object); //true 它是Student父类的父类
System.out.println(student instanceof Person); //true 它是Student的父类
System.out.println(student instanceof Student); //true 它本身就是Student类
//System.out.println(student instanceof Teacher); //编译错误
//System.out.println(student instanceof String); //编译错误
System.out.println("=================================");
Person person01 = new Person();
System.out.println(person01 instanceof Object); //true 它是Person的父类
System.out.println(person01 instanceof Person); //true 它是Person本身
System.out.println(person01 instanceof Student); //false 它是Person的子类
System.out.println(person01 instanceof Teacher); //false 它是Person的子类
//System.out.println(person01 instanceof String); //编译错误
}
}
类型转换
类型转换从低向高转换不需要强制转换,直接就能转
package com.oop;
import com.oop.demo05.Person;
import com.oop.demo05.Student;
public class Application {
public static void main(String[] args) {
//高 低
Person person = new Student();
}
}
如果想要从高往低转,那么就需要强制转换,比如说,person想要调用子类Student中的go方法,就需要先从Person转换成Student,才能调用
package com.oop;
import com.oop.demo05.Person;
import com.oop.demo05.Student;
import com.oop.demo05.Teacher;
public class Application {
public static void main(String[] args) {
Person person = new Student();
((Student)person).go(); //从Person转换为Student
}
}
子类转换成父类,可能会丢失自己的一些方法
总结:
1.父类的引用指向之类的对象
2.把子类转换成父类,向上转型
3.把父类转换成子类。向下转型 需要强制转换
4.方便方法的调用,减少重复的代码