1.什么是多态?
我认为:在Java的学习中,同一个方法,但通过在原有类的基础上新建类,执行方法的重写,来实现一个方法可以输出不同的结果,达到不同的功能。
比如我建立一个Person类,类里面有一个Study的方法,我在Person类的基础上建立Student 和Worker ,使这两个类继承Person里的方法,然后Student里的方法体是输出学生要上课学习知识,而Worker里面是输出打工人要去实践学习成果收获工作经验。
只需要在最后的测试类中,使用“向上转换类型”【父类句柄=子类对象】,便可通过Study(person),根据建立的对象,去输出相应的学习状态。
2.为什么要使用多态?
用课上ppt的代码实练来解释:
建立一个 Dog类和一个Penguin类,然后建立一个Master类和MasterTest测试类。Master类中要针对健康值建立Cure方法。
(1)未使用多态:
public class Fmaster {
public void Cures(Dogs dogs){
if (dogs.getHealthyNum()<50){
dogs.setHealthyNum(60);
System.out.println("狗狗要打针 ");
}else{
System.out.println("非常健康的狗狗");
}
}
public void Cures(Penguins penguins){
if (penguins.getHealthyNum()<50){
penguins.setHealthyNum(100);
System.out.println("q仔病了");
}else{
System.out.println("q仔很健康诶");
}
}
//显而易见,在主人类中,使用方法重载,有多少个需要“看病”的对象,就要建立多少个方法
}
class Dogs {
private int HealthyNum;
public int getHealthyNum() {
return HealthyNum;
}
public void setHealthyNum(int healthyNum) {
HealthyNum = healthyNum;
}
}
class Penguins{
private int HealthyNum;
public int getHealthyNum() {
return HealthyNum;
}
public void setHealthyNum(int healthyNum) {
HealthyNum = healthyNum;
}
}
//以上的Dogs和Penguins类都要重复地建立HeathyNum以及对应的设置器和访问器
static class FmasterTest{
public static void main(String[] args) {
Dogs dogs=new Dogs();
Penguins penguins=new Penguins();
dogs.setHealthyNum(10);
penguins.setHealthyNum(140);
Fmaster fmaster=new Fmaster();
fmaster.Cures(dogs);
fmaster.Cures(penguins);
}
}
//在Test类中要一一地对应建立相应类的对象,然后主人每次去调用方法时都要修改以下里面的参数
(2)使用多态后:
class Pet{
private int Health;
public int getHealth() {
return Health;
}
public void setHealth(int health) {
Health = health;
}
public void tohospital(){
}
}
//在这里,我们可以看到,我们新建了一个Pet类,里面涉及的是Dog和Penguin类共有的特性
//然后在这个类下,建立一个tohospital的方法
class Dog extends Pet{
public void tohospital(){
this.setHealth(60);
System.out.println("狗狗要打针吃药");
this.setHealth(100);
System.out.println("健康的狗狗");
}
}
class Penguin extends Pet{
public void tohospital(){
this.setHealth(60);
System.out.println("Q仔要吃药疗养");
}
}
//让两个类都去继承Pet类,在这里可以知道,直接减少了代码量,无需一个个类再重复一个个地去定义声明Health,使用方法重写,调用父类的tohospital方法,填写“自己的功能体现”
public class Master {
public void Cure(Pet pet){
if (pet.getHealth()<50){
pet.tohospital();
}else{
System.out.println("非常健康!");
}
}
}
//只需要在主人类中建立一个Cure方法,在Cure方法中通过if-else判断调用Pet类的tohospital方法
class MasterTest{
public static void main(String[] args) {
Master master=new Master();
Pet pet=new Dog();
pet.setHealth(100);
master.Cure(pet);
Pet pet1=new Penguin();
pet1.setHealth(40);
master.Cure(pet1);
}
}
//使用了“向上转换类型”,父类句柄=子类对象
//主人在调用Cure方法时,就无需再改变参数
(3)对比总结:
首先可以看到其实是有减少冗余的代码量的;
其次:
- 第一点:使用多态,涉及到继承,通过重复共有的属性抽取出一个父类,让对应的类去继承,减少代码的冗余;
- 第二点:使用多态,利用到“方法重写”的知识点,否则就是“方法重载”;两个相比,前者比后者要简化一点,因为无需再去修改参数列表,只需要去修改方法体就可以;
- 第三点:使用多态,无需改变“主类”,每出现一个新的类就要去不断修改参数增加重复方法内容。只需要在新出现的类里面重写相应的方法,然后在测试类中新建对象向上转换类型,调用方法就可;
- 第四点:使用多态,减少代码的修改频率,可维护性也可恶意得到提高
虽然两种方法比较起来,使用多态的那一种看着似乎复杂了一点,但效率功能相比起来,后者会更好。
3.多态的类型:
(1)静态多态:编译时多态
- 适用于——方法重载,变量隐藏,static,final,private,构造方法的情况
- 编译看左边,执行看左边
- 编译看左边:就拿“父类句柄=子类对象”来说,在编译代码的时候,检测编译的子类成员变量或者成员方法等等其他的,在父类里面有没有;
- 执行看左边:如果编译的那个“东西”,只是子类有而父类没有,就会报错无法输出结果,如果子类有父类也有,那么输出是结果是以父类为准的
(2)动态多态:运行时多态
- 实现动态多态的条件:继承,方法重写,使用对象向上转型【父类句柄=子类对象】
- 编译看左边,执行看右边
- 编译看左边:同上;
- 执行看右边:如果编译的那个“东西”。如果子类有父类也有,那么输出是结果是以“右边的对象”就是子类的为准;
4.方法重写和方法重载:
(1)方法重写:用于父类子类。方法名相同,参数列表相同
(2)方法重载:用于同一个类下。方法名相同,参数列表不同
5.向上转型和向下转型:
(1)向上转型:
- 简单来说就是将子类对象看作是父类的对象;比如子类是猫,父类是动物,可以将猫看作是动物
- 定义格式:父类句柄=子类对象;
(2)向下转型:
- 父类对象向下转为子类,这里就要注意使用到强制转换;
- 定义格式:子类句柄=(子类)父类对象;
6.instanceof运算符:
- 作用:强制类型的判断,判断对象是否的某个类的实例
- 格式:对象 instanceof 类类型;
- 某个类对象的向上转型对象是该类的及其超类的对象