写关于多态的文章,是因为今天在手动重写Object类的equals()方法的时候,需要用到向下转型,然后发现对于多态这部的内容有点忘记了,于是复习了下,然后来写一下有关多态的内容,并且自己手打一遍,巩固下记忆。
首先说一下多态:多态是面向对象的三大基本特性之一(封装,继承和多态)。
那么多态的定义是什么呢,多态的定义:多态是子类对象的父类引用。也就是说,通过 父类 变量名=new 子类();的形式来将子类对象赋值给父类引用。这种形式也叫向上转型。
举个例子: 父类Person 子类Student
class Person{ //父类Person
int age;
String name;
}
class Student extends Person{ //子类Student
int age;
String name;
}
然后我们的向上转型就是这样的。
子类对象new Student() , 父类引用变量 p
Person p=new Student();
说到这种形式,我想起了在学习抽象类的时候是这样说的:抽象类不能实例化,也就是不能创建抽象类的对象。但是我们指导抽象类里不仅有抽象方法,还有非抽象方法,那么这些非抽象方法我们该如何调用呢?
如果这个非抽象方法是static类型的,那么我们可以通过类名直接调用。但如果是非静态方法的话,我们这里就可以用多态来实现方法的调用,也就是将父类引用变量指向子类对象,从而调用父类的方法,当然子类在继承父类的时候必须先重写父类中所有的抽象方法。
上面说了向上转型,那么当然还有一个向下转型了,向下转型就是将父类引用转化为子类引用,不然我们的父类对象是无法去使用子类的成员变量以及方法的。具体形式就是 :子类 子类变量名=(子类) 父类变量名
这种转型 有点类似之前学的基本数据类类型的强制转换
例子:
class Person{
int age;
String name;
//带参构造方法
public Person(String name,int age) {
this.age=age;
this.name=name;
}
@Override
public boolean equals(Object obj) {
Person other = (Person) obj; //向下转型
if (age != other.age)
return false;
if (name == null) {
if (other.name != null)
return false;
} else if (!name.equals(other.name))
return false;
return true;
}
}
上面的代码我是直接自动生成的equals方法,为了减少代码量,我将部分比较代码删去了。这里Person类的父类是Object类,而Object类想要调用子类的成员变量时,必须先将其向下转型,否则无法访问子类的成员变量以及方法。
下面给出为转型的实例:
可以看到,Object类的obj对象在未转型前是无法获取子类Person的成员变量的
这里我们说一下多态成员的特点:
例如: Person是一个父类,Student是一个子类 。但是他们都共同拥有成员变量name 和 age,那么我们在调用成员方法和成员变量的时候到底调用的是谁的呢?
调用成员变量的时候,调用的是父类的成员
调用成员方法的时候,调用的是子类的成员
这里我使用黑马的笔记内容中的知识:
多态的成员特点:
* 成员变量 编译时看的是左边,运行时看的左边
* 成员方法 编译时看的是左边,运行时看右边
* 静态方法 编译时看的是左边,运行时看的也是左边
*
* 编译时看的都是左边,运行时成员方法看的是右边,其他(成员变量和静态的方法)看的都是左边
Person p=new Student();
解释一下,编译器编译时都是先看等式的左边。然后执行时,调用成员变量是看等式的左边。也就是说执行时,左边时父类引用,那么我们调用的就是父类的成员变量。 调用成员方法的时候我们看右边,也就是说右边是子类,那么我们就调用子类的成员方法。调用静态方法其实就是 类名.静态方法 来实现调用,所以我们看的也是左边。
感觉我说的有点模糊了,蜜汁尴尬,希望不要嫌弃。