Java第三章第2节:继承与多态 之 多态性 实验+图解讲解

简介

👨‍💻个人主页@云边牧风
👨‍🎓小编介绍:欢迎来到云边牧风破烂的小星球🌝
📋专栏:Java基础知识
🔑本章内容:Java继承与多态 之 多态性、abstract 类和abstract方法、super关键字
记得 评论📝 +点赞👍 +收藏😽 +关注💞哦~

接着第三章Java基础进阶的学习,这一章的内容主要有👇:

3.1 类的继承(√)

3.2 对象的上转型对象(√)

3.3 多态性

3.4 abstract 类和abstract方法

3.5 super关键字

第1节已经完成了类的继承和对象的上传型对象的学习,第2节我们接着👇:

一、多态性

1.0首先搞明白啥是“多态”这个概念🤔

在第二章第1节我们讲到:封装、继承、多态是面向对象(OOP)的三大特性:

封装,说简单点就是合并属性和行为创建一种新的数据类型(通俗点就是把数据和对数据的操作封装在一个class里面),而继承就是建立数据类型之间的某种关系(is-a),而多态就是这种关系在实际场景的运用(看菜吃饭,把做什么和怎么做分开了)

那么来了🌹 

👉多态是同一个行为具有多个不同表现形式或形态的能力。

👉多态是指:同一个接口    使用不同的实例而执行不同操作

 可以理解为下图:

1.1类的多态性体现在两个方面:

方法的多态性 :即方法的 重载 见第二章第2节:类—>3.重载)
继承的多态性 :即应用 上转型对象 调用子类覆盖的方法,从而产生不同行为

1.2继承多态性的应用:

使所有的子对象都可以上塑为同一个父对象, 响应同一个方法请求 ,可以 仅声明一个父对象 而不需要为每个子类声明对象;
这样的代码容易理解,也 易于扩展

例如:宠物都有叫声,但不同宠物叫声不同👇

class Pet
void speak ()

class Kitty
void speak (){

System.out.println(“喵喵~”);

}

class Puppy

void speak (){

System.out.println(“汪汪~”);

}

执行:

Pet  a = new Kitty();

a.speak();

a = new Puppy();

a.speak();

运行结果:

  喵喵

  汪汪

再看几个代码加深一下理解:

①定义一个Car的类,包含了一个方法getSpeed() 

class Car{
    public int getSpeed(){
	return 120;
   }
}

②此时求行驶时间类Timer,可以定义一个方法getTime()

class Timer{
    double getTime(Car c, double len){
	return len/c.getSpeed();
    }
}

 ③执行的代码可以这么写:

class Application{
public static main(String args[]){
       Car c=new Car();//声明了一个Car的对象 c
       Timer timer=new Timer();//声明了一个Timer的对象 timer
       double t=timer.getTime(c,300);//使用timer的getTime(方法)
       System.out.println(t);
    }
}

 ④同理,我们模仿Car继续定义Bus类

class Bus{
    public int getSpeed(){
	return 100;
   }
}

⑤定义Bike类 

class Bike{
    public int getSpeed(){
	return 30;
   }
}

⑥相应地,Timer可以改成这样的:

class Timer{
    double getTime(Car c, double len){
	return len/c.getSpeed();
    }
   double getTime(Bus c, double len){
	return len/c.getSpeed();
    }
  double getTime(Bike c, double len){
	return len/c.getSpeed();
    }
}

⑦又回到我们执行的代码,变成了这样的:

class Application{
public static main(String args[]){
       Car c=new Car();//声明了一个Car的对象 c     而且这时候可以根据需求修改类
       Timer timer=new Timer();//声明了一个Timer的对象 timer
       double t=timer.getTime(c,300);//使用timer的getTime(方法)
       System.out.println(t);
    }
}

这里的 Car c=new Car();  可以修改成

Bus bus = new Bus();或者Bike bike = new Bike();

而其他的都不需要改变

这么看可能还不是很省事,但处理的数据越来越多的时候,这样的结构优势就凸显出来了,代码能很大程度地精简、可读;而且哪个环节需要改动,就到目标板块进行修改,不需要每个代码都修改,多态性也是使Java为什么能够面向对象的原因了。

1.3上转型应用举例——数组

数组由 同一类型 的一连串对象或基本数据组成,并封装在同一数组名称下
问题:如果想在数组中保存不同类型的元素,怎么办?🤔

方法👉 可以使用上转型方法:

声明一个 Object 数组 存放不同类型元素的上转型对象;
使用某元素时,先下转型,然后再使用

 可以这么理解👇:

abstract 类和abstract方法

2.1、抽象类

用关键字 abstract 修饰的类称为 abstract 类(抽象类)

abstract class A

{ …

}

2.2、抽象类的特点:

抽象类可包含普通类所具有的任何成员,例如:构造方法,非 abstract 方法
与普通类不同的是,抽象类 可以有抽象方法 abstract 方法 ),并且对于 抽象方法,只允许声明,不允许实现

abstract class A

  abstract  int min(int x,int y);//后面不能接花括号{}/最多只能接个空的花括号

}

抽象类是没有具体实例对象的类, 不能使用 new 方法进行实例化 ;要想使用抽象类, 必须创建该类的子类,并且实现其中的抽象方法(覆盖) ,然后使用子类的对象。也正因为如此, 抽象类和抽象方法不能用 final 修饰

2.3、抽象类的应用:

抽象类是对一系列子类的 高层抽象 描述了 这些类的 公共属性和行为
如果这些类 都具有同一种行为,但行为的具体实施内容不同 ,那么可以在抽象类中将其定义为抽象方法,这样就 强制子类必须给出这些方法的具体实现

例如👇

宠物都会叫,但不同宠物叫声不同,因此,我们可以将“宠物”类定义为抽象类将“叫声”方法声明为抽象方法,这样就通知在创建“具体的宠物类”时必须给出具体的“叫声”。

abstract class Pet	{    //抽象类
    abstract void speak ();    //抽象方法
}

class Kitty{
void speak ()

}

class Puppy{

void speak ()

}

创建具体的宠物类时:

class Kitty extends Pet{
    void speak(){
	System.out.println("喵喵~");//必须给出具体的“叫声”
    }
}
class Puppy extends Pet{
    void speak(){
	System.out.println("汪汪~");//必须给出具体的“叫声”
     }
}

2.4、抽象类与抽象方法需要注意的问题:

一个抽象类的子类如果 不是抽象类 ,则它 必须覆盖父类中的所有抽象方法
只有抽象类才能具有抽象方法 ,即:如果一个类中含有抽象方法,则必须将这个类声明为抽象类
抽象类中 也可以包含非抽象方法
抽象类中 也可以没有抽象方法

例如:

abstract class A {
//类中含有抽象方法,则必须将这个类声明为抽象类
   abstract int add(int x,int y);//只有抽象类才能具有抽象方法
   int sub(int x,int y) {     //抽象类中也可以包含非抽象方法
      return x-y;
   }
}
class B extends A {    //B继承了A
   int add(int x,int y) {   
      return x+y;
   }
}

运行的代码为

public class Main{
   public static void main(String args[]) {
      B b=new B();
      int sum=b.add(30,20);      
      int sub=b.sub(30,20);         
      System.out.println("sum="+sum);  
      System.out.println("sum="+sub);  
      A a;                        
      a = b;                     
      sum=a.add(30,20); 
      sub=a.sub(30,20);       
      System.out.println("sum="+sum); 
      System.out.println("sum="+sub); 
   }
}

总代码为(复制粘贴可直接运行)👇:

abstract class A {
    //类中含有抽象方法,则必须将这个类声明为抽象类
    abstract int add(int x,int y);//只有抽象类才能具有抽象方法
    int sub(int x,int y) {     //抽象类中也可以包含非抽象方法
        return x-y;
    }
}
class B extends A {    //B继承了A
    int add(int x,int y) {
        return x+y;
    }
}
public class Main {
    public static void main(String[] args) {
        B b=new B();
        int sum=b.add(30,20);
        int sub=b.sub(30,20);
        System.out.println("sum="+sum);
        System.out.println("sum="+sub);
        A a;
        a = b;
        sum=a.add(30,20);
        sub=a.sub(30,20);
        System.out.println("sum="+sum);
        System.out.println("sum="+sub);
    }
}

 

运行结果为:

why?👇

三、super关键字

super 可以理解为是指向自己超(父)类对象的一个指针,而这个超类指的是离自己最近的一个父类。

super 代表“ 父类
super 可以在子类的构造方法中 调用父类的构造方法
super 可以在子类的方法中 调用被隐藏的父类成员或者方法

super 的三种用法:

3.1普通的直接引用

与 this 类似,super 相当于是指向当前对象的父类,这样就可以用

 super.xxx 

来引用父类的成员

 

3.2子类中的成员变量或方法与父类中的成员变量或方法同名

直接上代码👇:

class Country {
    String name;
    void value() {
        name = "China";
    }
}

class City extends Country {
    String name;

    void value() {
        name = "Shanghai";
        super.value();      //调用父类的方法
        System.out.println(name);
        System.out.println(super.name);
    }
}
public class Main {
    public static void main(String[] args) {
        City c=new City();
        c.value();
    }
}

运行结果:

3.3引用构造函数

这个小编也不是很明白,毕竟用的不多,如果想学好super的使用(非常精通),可以看看其他博主的文章,小编这个一直没什么运用,可以跳过哈

四、本章的应用举例

       用类封装手机的基本属性和功能,要求手机即可以使用移动公司的SIM卡也可以使用联通公司SIM卡(可以使用任何公司提供的SIM卡)

1.设计抽象类

设计一个抽象类SIM,该类有三个抽象方法:giveNumber()setNumber()giveCorpName()

2.设计手机类

设计MobileTelephone,该类有useSIM(SIM card)方法

3.各公司手机卡类

设计SIMOfChinaMobileSIMOfChinaUnicom

关系图为:

代码为👇:

public abstract class SIM {
    	public abstract void setNumber(String n);
    	public abstract String giveNumber();
    	public abstract String giveCorpName();
}

public class MobileTelephone {
   	SIM card;
   	public void useSIM(SIM card) {
      		this.card=card;
   	}
   	public void showMess() {
      		System.out.println("使用的卡是:"+card.giveCorpName()+"提供的");
      		System.out.println("手机号码是:"+card.giveNumber());
   	}
}

public class SIMOfChinaMobile extends SIM {
    	String number;
    	public void setNumber(String n) 
	{
        		number = n;
    	}
    	public String giveNumber() {
        		return number;
    	}
     	public String giveCorpName() {
        		return "中国移动";
    	}
}
public class SIMOfChinaUnicom extends SIM {
    	String number;
    	public void setNumber(String n) {
        		number = n;
    	}
    	public String giveNumber() {
        		return number;
    	}
    	public String giveCorpName() {
        		return "中国联通";
    	}
}
public class Main {
   	public static void main(String args[]) {
      		MobileTelephone  telephone = new  MobileTelephone ();
      		SIM sim=new SIMOfChinaMobile();
      		sim.setNumber("15888888888");
      		telephone.useSIM(sim);
      		telephone.showMess();
      		sim=new SIMOfChinaUnicom();
      		sim.setNumber("13366666666");
      		telephone.useSIM(sim);
      		telephone.showMess();
   	}
}

 最后的代码为:

abstract class SIM {
    public abstract void setNumber(String n);
    public abstract String giveNumber();
    public abstract String giveCorpName();
}

class MobileTelephone {
    SIM card;
    public void useSIM(SIM card) {
        this.card=card;
    }
    public void showMess() {
        System.out.println("使用的卡是:"+card.giveCorpName()+"提供的");
        System.out.println("手机号码是:"+card.giveNumber());
    }
}
class SIMOfChinaMobile extends SIM {
    String number;
    public void setNumber(String n)
    {
        number = n;
    }
    public String giveNumber() {
        return number;
    }
    public String giveCorpName() {
        return "中国移动";
    }
}
class SIMOfChinaUnicom extends SIM {
    String number;
    public void setNumber(String n) {
        number = n;
    }
    public String giveNumber() {
        return number;
    }
    public String giveCorpName() {
        return "中国联通";
    }
}

public class Main {
    public static void main(String[] args) {
        MobileTelephone  telephone = new  MobileTelephone ();
        SIM sim=new SIMOfChinaMobile();
        sim.setNumber("15888888888");
        telephone.useSIM(sim);
        telephone.showMess();
        sim=new SIMOfChinaUnicom();
        sim.setNumber("13366666666");
        telephone.useSIM(sim);
        telephone.showMess();
    }
}

运行结果是:

五、本章总结

类的继承

    子类中的成员和方法

对象的上转型对象

    通过上转型对象能访问哪些成员和方法

多态性

    继承的多态(通过上转型对象实现)

abstract 类和 abstract 方法

    抽象类的特点及作用

super关键字

    作用及用法

练习题1:

在一个 公司管理信息系统 中,包括
普通员工( Employees), 其可能有的属性信息包括
员工号( employeeNumber
姓名( name)
地址( address)
电话号码( phoneNumber
管理者( Magagers ), 除具有普通员工所具有的属性及行为外,还具有下面的属性和行为
职责( responsibilities)
所管理的职员( listOfEmployees
工资的计算方法与一般员工不同;福利与一般员工不同
顾客( Customers), 可能有的属性信息包括
姓名( name)
地址( address)
电话号码( phoneNumber

练习题2:

       对于各种几何图形,一般都有求图形的面积、周长等方法。现在有圆、矩形和三角形三种图形,要求通过类来实现求三种图形的面积。

1.问题分析

       三种图形都有相同的方法,因此可以抽象出一个抽象类:图形类,该类有抽象的求面积方法。然后由该抽象类生成3个子类:圆类、矩形类、三角形类。在主类中实现求各类图形的面积。

 

        

以上两个练习题,如果小伙伴们喜欢,可以在评论区求代码❤❤❤

结束语:

以上是Jav第三章的全部内容,希望大家喜欢

下一节开始讲第四章接口与内部类

喜欢的可以点赞+关注哈 ❤

 

评论 1
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

当前余额3.43前往充值 >
需支付:10.00
成就一亿技术人!
领取后你会自动成为博主和红包主的粉丝 规则
hope_wisdom
发出的红包

打赏作者

云边牧风

你的鼓励将是我创作的最大动力

¥1 ¥2 ¥4 ¥6 ¥10 ¥20
扫码支付:¥1
获取中
扫码支付

您的余额不足,请更换扫码支付或充值

打赏作者

实付
使用余额支付
点击重新获取
扫码支付
钱包余额 0

抵扣说明:

1.余额是钱包充值的虚拟货币,按照1:1的比例进行支付金额的抵扣。
2.余额无法直接购买下载,可以购买VIP、付费专栏及课程。

余额充值