前言
面向对象程序设计的三大支柱是封装、继承和多态。继承关系使一个子类能继承父类的特征,并且附加一些新特征。子类是它的父类的特殊化,每个子类的实例是其父类的实例,但是反过来不成立、因此、总可以将子类的实例传给需要父类型的参数。多态就意味着父类型的变量可以引用子类型的参数。
向上转型和向下转型
在我们学习程序设计语言的过程中,我们似乎总能用到强制类型转换,比如将一个String类型转换为int类型。而像这样的转型是有前提的,那就是:这两个类型是否存在着某种关联关系。
由此我们就可以联想到类:类与类之间是否可以相互转换呢?这里我们就要说到向上转型了。
向上转型(upcasting):
public class Human {
public void sleep() {
System.out.println("Human sleep..");
}
public static void main(String[] args) {
Male m = new Male();
m.sleep();
Human h = new Male();// (1) 向上转型
h.sleep(); //(2)动态绑定
//h.speak(); //(3)此方法不能编译,报错说Human类没有此方法
}
}
class Male extends Human {
@Override
public void sleep() {
System.out.println("Male sleep.");
}
public void speak () {
System.out.println("I am Male");
}
}
class Female extends Human {
@Override
public void sleep() {
System.out.println("Female sleep.");
}
public void speak() {
System.out.println("I am Female");
}
}
运行结果为:Male sleep.
Male sleep.
仔细研究上方代码,我们可以发现,Human类是Male类和Female类的父类。在主方法中,我们可以看到声明了一个Male对象m,再调用了m的sleep方法,很显然这句话会输出Male sleep.
但是当声明h对象时,却出现了两个类,其中h的声明类型是Human类(父类),实际类型则是Male类,调用h.sleep()方法,会输出 Male sleep. 调用h.speak()方法则会出错。
由此我们可以知道向上转型:1、向上转型不要强制转型。2、父类引用指向的或者调用的方法是子类的方法,这个叫动态绑定 。3、向上转型后,父类应用不能调用子类自己的办法。
向下转型(downcasting):
//接上段
//向下转型:成功
Male m2 = new Male();
Human h2 = m2; //向上转型
m2 = (Male)h2; //向下转型
m2.speak();
//向下转型:失败
Human h3 = new Human();
Male m3 = (Male)h3;
m3.speak(); //运行时会出现错误,可以用instanceof诊断
//向下转型:类型防护
Human h4 = new Human();
if (h4 instanceof Male){ //因为h4不是Male的实例,所以不执行if内部代码
Male m4 = (Male)h4;
m4.speak;
}
向下转型一般用的比较少。
instanceof关键字:
作用:用来判断某个对象是否属于某种数据类型。
注意:返回类型为布尔类型
其实多态的核心就是向上转型。
所以说,多态的定义与使用格式就是: 定义格式:父类类型 变量名=new 子类类型();
多态的应用
多态:父类型对象访问子类型重写的方法。
使用场景:1、循环调用父类对象,访问不同派生类方法。
2、实参是子类,形参是父类。
场景一应用:
//Person类
public class Person {
private String name;
private int age;
public Person() {
}
public Person(String name, int age) {
this.name = name;
this.age = age;
}
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 String say() { // 返回名字和年龄
return name + "\t" + age;
}
}
//Student类
public class Student extends Person {
private double score;
public Student() {
}
public Student(String name, int age, double score) {
super(name, age);
this.score = score;
}
public Student(String name, int age) {
super(name, age);
}
public Student(double score) {
this.score = score;
}
//重写父类say方法
@Override
public String say() {
return super.say() + " score=" + score;
}
//学生特有的方法
public void study() {
System.out.println("学生 " + getName() + "正在学java");
}
}
//Teacher类
public class Teacher extends Person {
public double salary;
public Teacher(String name, int age, double salary) {
super(name, age);
this.salary = salary;
}
public double getSalary() {
return salary;
}
public void setSalary(double salary) {
this.salary = salary;
}
@Override
public String say() {
return super.say() + " salary=" + salary;
}
//特有的方法
public void teach() {
System.out.println("老师" + getName() + "正在讲java课程");
}
}
public class PloyArray {
public static void main(String[] args) {
Person[] persons = new Person[5];
persons[0] = new Person("jack", 20);
persons[1] = new Student("jack", 18, 100);
persons[2] = new Student("smith", 19, 30.1);
persons[3] = new Teacher("scott", 30, 20000);
persons[4] = new Teacher("king", 50, 25000);
for (int i = 0; i < persons.length; i++) {
System.out.println(persons[i].say());
// System.out.println(persons[i] instanceof Person);
// if (persons[i] instanceof Student) {
// ((Student)persons[i]).study();
// } else if (persons[i] instanceof Teacher) {
// ((Teacher)persons[i]).teach();
// }
}
}
}
场景二应用:
package Sample;
public class DynamicBindingDemo {
public 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 Object {
@Override
public String toString() {
return "Person";
}
}