首页 > 编程语言 >Java 继承和多态(进阶介绍 十六)

Java 继承和多态(进阶介绍 十六)

时间:2024-08-06 13:52:53浏览次数:14  
标签:Java 进阶 多态 class extends Animal Mammal mailCheck public

目录

Java 继承

IS-A 关系

实例

实例

instanceof 关键字

HAS-A 关系

例子

Java 多态

简单的例子

虚方法

多态的实现方式

方式一:重写

方式二:接口


Java 继承

继承是所有 OOP 语言和 Java 语言不可缺少的组成部分。

继承是 Java 面向对象编程技术的一块基石,是面向对象的三大特征之一,也是实现软件复用的重要手段,继承可以理解为一个对象从另一个对象获取属性的过程。

如果类 A 是类 B 的父类,而类  B 是类 C 的父类,我们也称类 C 是 A 的子类,类 C 是从类 A 继承而来的。在 Java 中,类的继承是单一继承,也就是说,一个子类只能拥有一个父类。

继承中最常使用的两个关键字是 extends 和 implements 。

这两个关键字的使用决定了一个对象和另一个对象是否是 IS-A (是一个)关系。

通过使用这两个关键字,我们能实现一个对象获取另一个对象的属性。

所有 Java 的类均是由 java.lang.Object 类继承而来的,所以 Object 是所有类的祖先类,而除了 Object 外,所有类必须有一个父类。

通过 extends 关键字可以申明一个类是继承另外一个类而来的,一般形式如下:

// A.java
public class A {
    private int i;
    protected int j;
 
    public void func() {
 
    }
}
 
// B.java
public class B extends A {
    public int z;

    public void fund(){

    }
    
}

以上的代码片段说明,类 B 由类 A 继承而来的,类 B 是类 A 的子类。而类 A 是 Object 的子类,这里可以不显示地声明。

作为子类,类 B 的实例拥有类 A 所有的成员变量,但对于 private 类型的成员变量类 B 却没有访问权限,这保障了类 A 的封装性。


IS-A 关系

IS-A 就是说:一个对象是另一个对象的一个分类。

下面是使用关键字 extends 实现继承。

public class Animal{
}

public class Mammal extends Animal{
}

public class Reptile extends Animal{
}

public class Dog extends Mammal{
}

基于上面的例子,以下说法是正确的:

  • Animal 类是 Mammal 类的父类。
  • Animal 类是 Reptile 类的父类。
  • Mammal 类和 Reptile 类是 Animal 类的子类。
  • Dog 类既是 Mammal 类的子类又是 Animal 类的子类。

分析以上示例中的 IS-A 关系,如下:

  • Mammal IS-A Animal
  • Reptile IS-A Animal
  • Dog IS-A Mammal

因此 : Dog IS-A Animal

通过使用关键字 extends ,子类可以继承父类的除 private 属性外所有的属性。

我们通过使用 instanceof 操作符,能够确定 Mammal IS-A Animal

实例

public class Dog extends Mammal{
   public static void main(String args[]){

      Animal a = new Animal();
      Mammal m = new Mammal();
      Dog d = new Dog();

      System.out.println(m instanceof Animal);
      System.out.println(d instanceof Mammal);
      System.out.println(d instanceof Animal);
   }
}

以上实例编译运行结果如下:

true
true
true

介绍完 extends 关键字之后,我们再来看下 implements 关键字是怎样使用来表示 IS-A 关系。

Implements 关键字在类继承接口的情况下使用, 这种情况不能使用关键字 extends 

实例

public interface Animal {}

public class Mammal implements Animal{
}

public class Dog extends Mammal{
}

instanceof 关键字

可以使用 instanceof 运算符来检验 Mammal 和 dog 对象是否是 Animal 类的一个实例。

interface Animal{}

class Mammal implements Animal{}

public class Dog extends Mammal{
   public static void main(String args[]){

      Mammal m = new Mammal();
      Dog d = new Dog();

      System.out.println(m instanceof Animal);
      System.out.println(d instanceof Mammal);
      System.out.println(d instanceof Animal);
   }
} 

以上实例编译运行结果如下:

true
true
true

HAS-A 关系

HAS-A 代表类和它的成员之间的从属关系。这有助于代码的重用和减少代码的错误。

例子

public class Vehicle{}
public class Speed{}
public class Van extends Vehicle{
	private Speed sp;
} 

Van 类和 Speed 类是 HAS-A 关系( Van 有一个 Speed ),这样就不用将 Speed 类的全部代码粘贴到 Van 类中了,并且 Speed 类也可以重复利用于多个应用程序。

在面向对象特性中,用户不必担心类的内部怎样实现。

Van 类将实现的细节对用户隐藏起来,因此,用户只需要知道怎样调用 Van 类来完成某一功能,而不必知道 Van 类是自己来做还是调用其他类来做这些工作。

Java 只支持单继承,也就是说,一个类不能继承多个类。

下面的做法是不合法的:

public class extends Animal, Mammal{} 

Java 只支持单继承(继承基本类和抽象类),但是我们可以用接口来实现(多继承接口来实现),代码结构如下:

public class Apple extends Fruit implements Fruit1, Fruit2{}

一般我们继承基本类和抽象类用 extends 关键字,实现接口类的继承用 implements 关键字

Java 多态


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

多态性是对象多种表现形式的体现。

比如我们说"宠物"这个对象,它就有很多不同的表达或实现,比如有小猫、小狗、蜥蜴等等。那么我到宠物店说"请给我一只宠物",服务员给我小猫、小狗或者蜥蜴都可以,我们就说"宠物"这个对象就具备多态性。

接下来让我们通过实例来了解Java的多态。

简单的例子

public interface Vegetarian{}
public class Animal{}
public class Deer extends Animal implements Vegetarian{}

因为Deer类具有多重继承,所以它具有多态性。以上实例解析如下:

  • 一个 Deer IS-A(是一个) Animal
  • 一个 Deer IS-A(是一个) Vegetarian
  • 一个 Deer IS-A(是一个) Deer
  • 一个 Deer IS-A(是一个)Object

在Java中,所有的对象都具有多态性,因为任何对象都能通过IS-A测试的类型和Object类。

访问一个对象的唯一方法就是通过引用型变量。

引用型变量只能有一种类型,一旦被声明,引用型变量的类型就不能被改变了。

引用型变量不仅能够被重置为其他对象,前提是这些对象没有被声明为final。还可以引用和它类型相同的或者相兼容的对象。它可以声明为类类型或者接口类型。

当我们将引用型变量应用于Deer对象的引用时,下面的声明是合法的:

Deer d = new Deer();
Animal a = d;
Vegetarian v = d;
Object o = d;

所有的引用型变量d,a,v,o都指向堆中相同的Deer对象。


虚方法

我们将介绍在Java中,当设计类时,被重写的方法的行为怎样影响多态性。

我们已经讨论了方法的重写,也就是子类能够重写父类的方法。

当子类对象调用重写的方法时,调用的是子类的方法,而不是父类中被重写的方法。

要想调用父类中被重写的方法,则必须使用关键字super。

/* 文件名 : Employee.java */
public class Employee
{
   private String name;
   private String address;
   private int number;
   public Employee(String name, String address, int number)
   {
      System.out.println("Constructing an Employee");
      this.name = name;
      this.address = address;
      this.number = number;
   }
   public void mailCheck()
   {
      System.out.println("Mailing a check to " + this.name
       + " " + this.address);
   }
   public String toString()
   {
      return name + " " + address + " " + number;
   }
   public String getName()
   {
      return name;
   }
   public String getAddress()
   {
      return address;
   }
   public void setAddress(String newAddress)
   {
      address = newAddress;
   }
   public int getNumber()
   {
     return number;
   }
}

假设下面的类继承Employee类:

/* 文件名 : Salary.java */
public class Salary extends Employee
{
   private double salary; //Annual salary
   public Salary(String name, String address, int number, double
      salary)
   {
       super(name, address, number);
       setSalary(salary);
   }
   public void mailCheck()
   {
       System.out.println("Within mailCheck of Salary class ");
       System.out.println("Mailing check to " + getName()
       + " with salary " + salary);
   }
   public double getSalary()
   {
       return salary;
   }
   public void setSalary(double newSalary)
   {
       if(newSalary >= 0.0)
       {
          salary = newSalary;
       }
   }
   public double computePay()
   {
      System.out.println("Computing salary pay for " + getName());
      return salary/52;
   }
}

现在我们仔细阅读下面的代码,尝试给出它的输出结果:

/* 文件名 : VirtualDemo.java */
public class VirtualDemo
{
   public static void main(String [] args)
   {
      Salary s = new Salary("Mohd Mohtashim", "Ambehta, UP", 3, 3600.00);
      Employee e = new Salary("John Adams", "Boston, MA", 2, 2400.00);
      System.out.println("Call mailCheck using Salary reference --");
      s.mailCheck();
      System.out.println("\n Call mailCheck using Employee reference--");
      e.mailCheck();
    }
}

以上实例编译运行结果如下:

Constructing an Employee
Constructing an Employee
Call mailCheck using Salary reference --
Within mailCheck of Salary class
Mailing check to Mohd Mohtashim with salary 3600.0

Call mailCheck using Employee reference--
Within mailCheck of Salary class
Mailing check to John Adams with salary 2400.0

例子中,我们实例化了两个Salary对象。一个使用Salary引用s,另一个使用Employee引用。

编译时,编译器检查到mailCheck()方法在Salary类中的声明。

在调用s.mailCheck()时,Java虚拟机(JVM)调用Salary类的mailCheck()方法。

因为e是Employee的引用,所以调用e的mailCheck()方法则有完全不同的结果。

当编译器检查e.mailCheck()方法时,编译器检查到Employee类中的mailCheck()方法。

在编译的时候,编译器使用Employee类中的mailCheck()方法验证该语句, 但是在运行的时候,Java虚拟机(JVM)调用的是Salary类中的mailCheck()方法。

该行为被称为虚拟方法调用,该方法被称为虚拟方法。

Java中所有的方法都能以这种方式表现,借此,重写的方法能在运行时调用,不管编译的时候源代码中引用变量是什么数据类型。

多态的实现方式

方式一:重写

http://t.csdnimg.cn/Y4AjJ

方式二:接口

  • 1. 生活中的接口最具代表性的就是插座,例如一个三接头的插头都能接在三孔插座中,因为这个是每个国家都有各自规定的接口规则,有可能到国外就不行,那是因为国外自己定义的接口类型。
  • 2. java中的接口类似于生活中的接口,就是一些方法特征的集合,但没有方法的实现。具体可以看 java接口 这一章节的内容

标签:Java,进阶,多态,class,extends,Animal,Mammal,mailCheck,public
From: https://blog.csdn.net/weixin_64261178/article/details/140944150

相关文章

  • Java计算机毕业设计家乐在线家装平台(开题报告+源码+论文)
    本系统(程序+源码)带文档lw万字以上 文末可获取一份本项目的java源码和数据库参考。系统程序文件列表开题报告内容研究背景随着互联网的普及和人们生活水平的提高,家装行业正经历着前所未有的变革。传统家装模式存在信息不对称、流程繁琐、效率低下等问题,难以满足消费者日益......
  • Java计算机毕业设计课程在线测评系统(开题报告+源码+论文)
    本系统(程序+源码)带文档lw万字以上 文末可获取一份本项目的java源码和数据库参考。系统程序文件列表开题报告内容研究背景随着信息技术的飞速发展,在线教育已成为教育领域的重要组成部分,其灵活性和便捷性受到广大师生的青睐。然而,如何有效评估在线教育的学习效果,确保教学质......
  • Java计算机毕业设计咖啡馆管理系统(开题报告+源码+论文)
    本系统(程序+源码)带文档lw万字以上 文末可获取一份本项目的java源码和数据库参考。系统程序文件列表开题报告内容研究背景随着咖啡文化的普及和消费者对品质生活追求的不断提升,咖啡馆作为休闲聚会、商务洽谈的重要场所,其数量与规模在全球范围内迅速增长。然而,传统的手工管......
  • Java计算机毕业设计家教服务网(开题报告+源码+论文)
    本系统(程序+源码)带文档lw万字以上 文末可获取一份本项目的java源码和数据库参考。系统程序文件列表开题报告内容研究背景在当今社会,随着教育竞争的日益激烈和家长对孩子教育质量的重视,家教服务已成为许多家庭提升孩子学习成绩、培养综合素质的重要途径。然而,传统的家教服......
  • 基于Java+SpringBoot+Mysql实现的在线电影订票系统部分功能设计与实现五
    一、前言介绍:1.1项目摘要随着互联网技术的飞速发展和普及,人们的娱乐消费方式发生了巨大变化。在线娱乐平台,特别是电影订票系统,成为了现代人观影的主要选择之一。这一变化主要得益于以下几个方面的因素:生活节奏的加快:现代人的生活节奏越来越快,时间变得尤为宝贵。在线电影......
  • 基于Java+SpringBoot+Mysql实现的在线电影订票系统部分功能设计与实现六
    一、前言介绍:1.1项目摘要随着互联网技术的飞速发展和普及,人们的娱乐消费方式发生了巨大变化。在线娱乐平台,特别是电影订票系统,成为了现代人观影的主要选择之一。这一变化主要得益于以下几个方面的因素:生活节奏的加快:现代人的生活节奏越来越快,时间变得尤为宝贵。在线电影......
  • 计算机毕业设计必看必学!! 86393 基于微服务架构的餐饮系统的设计与实现,原创定制程序,
    摘   要近年来,我国经济和社会发展迅速,人们物质生活水平日渐提高,餐饮行业更是发展迅速,人们对于餐饮行业的认识和要求也越来越高。传统形式的餐饮行业都是以人为本,管理起来需要很多人力、物力、财力,既不方便管理者的管理,也不方便顾客实时了解餐厅动态,给传统餐......
  • Java包装类;字符串处理类:String;StringBuffer;StringBuilder;字符串处理类的常用方法;异常
    一,包装类      什么是包装类:         包装类是对于八种基本数据类型而言的,八种数据类型都有其对应的包装类。         以前定义变量,经常使用基本数据类型,对于基本数据类型来说,它就是一个数,加点属性,加点方法,加点构造器。  ......
  • Java集合:Collection and Map;ArrayList;LinkList;HashSet;TreeSet;HashMap;TreeMap;Iterator:
        集合介绍:                        是一组变量类型(容器),跟数组很像。一,引用集合的原因(必要性):                  A:数组的空间长度固定,一旦确定不可以更改。多了浪费,少了报错。          B:使用数......
  • kotlin 与java 接口不兼容@FunctionalInterface
    需求:获取当前方法名为了获取当前方法名已知的有1.堆栈获取2.通过classs的enclosingMethod.name比较准确的是enclosingMethod,但是为了获取这个还需要一个内部类,于是用到了Runable,但是run方法没有返回值于是出现了神奇问题1.照Runnable抄一份:源码如下:@FunctionalInterfacepu......