【Java】—— 继承

1.继承

1.1 为什么需要继承

在使用类的时候,是将生活中的实物,抽象到代码中进行表示,在生活中,很多实物都是存在关联的,例如 哈士奇、中华田园犬、萨摩耶 都是狗,他们有共性信息,也有属于自己的特点

共同点:有一个头,四条腿,一个尾巴等等

不同点:哈士奇就是活泼好动,拆家小能手。中华田园犬性格温顺,独立能力强。萨摩耶“微笑天使”

继承 就可以将这些共同点提取出来作为父类,而不同点就可以基于 “父类” 派生出 “子类”,将不同的特点放到子类中。这样,就可以实现 “代码复用”

1.2 继承的概念

通过 “父类” 产生 “子类” 的过程,就可以称为 “派生”。

父类 派生出 子类

子类 继承自 父类

父类(parent class)又称 基类(base class)、超类(super class)

分别对应

子(孩子的子)类(child class)又称 派生类(derived class)子(子集的子)类(sub class)

1.3 继承的语法

首先要创造一个父类,与普通的类一样,在创建子类时借助 extends 关键字

语法格式:

修饰符 class 子类 extends 父类 {

    //......

}

代码示例

//创建一个父类,用来表示动物
public class Animal {
    private String name;//名字
    private int age;//年龄
    public void eat(String food){
        //吃东西的方法
        System.out.println(name + "正在吃" + food);
    }
    public void sleep(){
        //睡觉的方法
        System.out.println(name + "正在睡觉");
    }
}}
//再定义一个类表示狗,继承自动物类
//这个时候 dog 就有了 animal 所有的属性和方法
//只需要再写出 dog 独有的属性和方法
public class Dog extends Animal {
    public void bark(){
        System.out.println("汪汪汪");
    }
}
public class Test {
    //通过 Test 类去测试前面所写的类
    public static void main(String[] args) {
        Dog dog = new Dog();//实例化dog
        dog.eat("骨头");
        dog.sleep();
        dog.bark();
    }
}

这样就实现了通过子类调用父类的属性和方法,接下来我们给动物的名称补充一下 

    public String getName() {
        return name;
    }

    public void setName(String name) {
        this.name = name;
    }
dog.setName("大黄");

如果在叫声前加上 name ,就会发现编译错误

报错信息:“name” 在 “object2.Animal” 中拥有私有访问权限

这是 private 限制了该属性不能在类的外部被访问,即使是子类也不行,解决方案依旧是使用 getter 方法

1.4 父类成员方法

1.4.1 子类中访问父类的成员变量

子类和父类不存在同名成员变量

//父类
public class Animal {
    public String name = "父类中的name";//名字
    public void eat(String food){
        System.out.println(name + "正在吃" + food);
    }
}


//子类
public class Dog extends Animal {
    
    public String name = "子类中的name"
}

public class Test {
    public static void main(String[] args) {
        Dog dog = new Dog();//实例化dog
        dog.eat("骨头");
        System.out.println(dog.name);
    }
}

//运行结果:
//父类中的name正在吃骨头
//子类中的name

这段代码中可以得到两个结论:

  • 来自父类的方法调用的就是父类中的属性;
  • 当子类和父类中有重名的属性,会优先调用子类的属性。

访问方法与属性类似,先看参数有无相同,依旧是子类先,父类后,都没有则报错

语法上使用了就近原则,在实际代码中不建议这样写,影响了代码的可读性

1.4.2 super 关键字

如果迫不得已出现了这种重名的情况,又想要直接访问父类,就可以通过 super 关键字指定要访问的父类的属性

this 指向当前对象的引用

super 指向当前对象内部的父类对象的引用

没有出现重名:

this 访问的属性就是父类,super 访问的属性还是父类

这里两者是一致的

出现重名的情况:

this 访问的就是子类的,super 访问的就是父类的

这里两者就不一致了

代码示例:

//父类
public class Animal {
    public String name = "父类中的name";//名字
}


//子类
public class Dog extends Animal {
    public String name = "子类中的name"
    public void bark(){
        //访问父类的属性
        System.out.println(super.name + "汪汪汪");
        //访问子类的属性
        System.out.println(this.name + "汪汪汪");
    }
}

public class Test {
    public static void main(String[] args) {
        Dog dog = new Dog();//实例化dog
        dog.bark();
    }
}

//运行结果:
父类中的name汪汪汪
子类中的name汪汪汪

注意事项:super 和 this 一样,不能在静态方法中使用 

super 也可以调用方法,方法类似只放代码不作介绍

//父类
public class Animal {
    public void bark(){
        System.out.println("父类");
    }
}


//子类
public class Dog extends Animal {
    public void bark(){
        super.bark();
        System.out.println("子类");
    }
}

public class Test {
    public static void main(String[] args) {
        Dog dog = new Dog();//实例化dog
        dog.bark();
    }
}

//运行结果:
父类
子类

super 还可以用来调用构造方法

在创建完父类和子类继承后,写上构造方法,这是会发现

编译报错:“object2.Parent” 中没有可用的默认构造函数

这是因为构造子类时需要先构造父类(父类中的属性被子类继承)

如果父类只有一个无参数的默认构造方法,这里是不会报错的(编译器会在子类自动添加super)

public class Parent {
    public Parent(){
        System.out.println("父类构造方法");
    }
}
public class Child extends Parent{
    public Child(){
    System.out.println("子类的构造方法");
    }
}

当父类构造方法带有参数时,就需要手动调用父类的构造方法并且传参

public class Parent {
    public Parent(int x){
        System.out.println("父类构造方法");
    }
}

public class Child extends Parent{
    public Child(){
        super(10);
        System.out.println("子类的构造方法");
    }
}
}

注意事项:

  • 这里的 super 的顺序必须在第一个,先构造了父类才可以再构造子类
  • super 只能在子类构造方法中出现一次,且不能和 this 同时出现

1.5 访问修饰限定符-protected 关键字

protected 关键字,和 pubilc、private 是并列关系

在Java中访问控制权限的关键字有三个,权限等级分为四种

还有一种情况是什么都不写,用 default 来表示,不需要真的去写

代码示例:

因为涉及到不同包之间的操作,所以需要提前创好两个不同的包

接下来通过代码来测试限定符的权限

1.5.1 default

default 在当前包 类内部的使用(可以访问):

package object3.pakeage1;

public class Test {
    //不使用任何修饰符来限制权限
    //此时权限就是 default 级别
    int x = 10;

    public static void main(String[] args) {
        Test t = new Test();
        System.out.println(t.x);
    }
}

default 在同一包 中其他类使用(可以访问):

package object3.pakeage1;

public class Test2 {
    public static void main(String[] args) {
        Test t = new Test();
        // default 这样的属性,是可以被同一个包中的其他类使用的
        System.out.println(t.x);
    }
}

default 在不同包中的使用(编译错误):

//跨包进行访问

//如果访问的类就在当前包中,就不需要 import
//如果是在其他包中就需要 import
import object3.pakeage1.Test;
public class Test3 {
    public static void main(String[] args) {
        Test t = new Test();
        //已经超出 default 权限
        System.out.println(t,x);
    }
}

错误信息:

1.5.2 protected

protected 在当前包 类内部的使用(可以访问)

public class Test {
    //使用 protected 来修饰
    protected int x = 10;

    public static void main(String[] args) {
        Test t = new Test();
        // default 级别的属性可以在类内部使用
        System.out.println(t.x);
    }
}

protected 在同一包 中其他类使用(可以访问):

public class Test2 {
    public static void main(String[] args) {
        Test t = new Test();
        System.out.println(t.x);
    }
}

protected 在不同包的不相关类中使用(编译错误):

package object3.pakeage2;

import object3.pakeage1.Test;
public class Test3 {
    public static void main(String[] args) {
        Test t = new Test();
        System.out.println(t.x);
    }
}

protected 在不同包的子类中使用:

package object3.pakeage2;

import object3.pakeage1.Test;

public class Test4 extends Test {
    public static void main(String[] args) {
        Test4 t4 = new Test4();
        System.out.println(t4.x);
    }
}

1.6 继承的方式

Java是一个单继承体系,只能有一个父类

单继承

public class A{
    .....
}

public class B extends A{
    .....
}

多层继承

public class A{
    .....
}

public class B extends A{
    .....
}

public class C extends B{
    .....
}

不同类继承同一个类

public class A{
    .....
}

public class B extends A{
    .....
}

public class C extends A{
    .....
}

多继承(Java不支持)

public class A{
    .....
}

public class B{
    .....
}

public class C extends A,B{
    .....
}

1.7 final 关键字

主要作用:

1、使用 final 修饰变量后,变量不再可以被修改

2、使用 final 修饰类,该类就不可被继承

3、使用 final 修饰方法,该方法不能被子类重写

1.8 继承和组合

从设计的角度来看待 类 之间的关系就有如下两种

is - a 的关系        继承

动物 -> 狗 -> 哈士奇

见到一个哈士奇,就可以称它 “一只狗” ,也可以 “一只动物”

这里的核心就是 “

has - a 的关系        组合

一个头,一个尾巴,有四条腿

这些肢体组成了这只猫

这里的核心就是 “

组合和继承都可以实现代码复用,应该使用继承还是组合,需要根据应用场景来选择,一般建议:能用组合尽量用组合

本文来自互联网用户投稿,该文观点仅代表作者本人,不代表本站立场。本站仅提供信息存储空间服务,不拥有所有权,不承担相关法律责任。如若转载,请注明出处:/a/930298.html

如若内容造成侵权/违法违规/事实不符,请联系我们进行投诉反馈qq邮箱809451989@qq.com,一经查实,立即删除!

相关文章

2024-12-06 Unity Addressables3——资源加载

文章目录 1 引用加载1.1 Addressables 的资源引用类1.2 加载资源1.3 加载场景1.4 释放资源 2 Label 介绍3 动态加载3.1 加载单个资源3.2 加载多个资源 Unity 版本:6000.0.26f1c1Addressables 版本:2.3.1 1 引用加载 1.1 Addressables 的资源引用类 Ass…

【WRF理论第十三期】详细介绍 Registry 的作用、结构和内容

目录 1. Introduction:介绍 Registry 的作用和功能。2. Registry Contents:详细描述 Registry 的结构和内容,包括各个部分的条目类型。2.1. DIMSPEC ENTRIES(维度规格条目)2.2. STATE ENTRIES(状态变量条目…

在阿里云/Linux环境搭建Gitblit服务

在阿里云/Linux环境搭建Gitblit服务 1. 整体描述2. 前期准备3. 安装步骤3.1 下载gitblit3.2 上传gitblit3.3 解压文件3.4 修改文件配置3.5 启动gitblit3.6 安全组配置 4. 总结 1. 整体描述 前段时间买了一个阿里云服务器,2核2G,3M固定带宽的配置&#x…

鸿蒙arkts怎么打印一个方法的调用堆栈

做鸿蒙开发的时候,也想看一下一个方法到底是哪里调用的,工程太大,断点太麻烦,可以加堆栈日志。 在你的方法中加上这两句,就可以跟到堆栈日志 let err new Error() console.log(>>>>>>err.stack) …

116. UE5 GAS RPG 实现击杀掉落战利品功能

这一篇,我们实现敌人被击败后,掉落战利品的功能。首先,我们将创建一个新的结构体,用于定义掉落体的内容,方便我们设置掉落物。然后,我们实现敌人死亡时的掉落函数,并在蓝图里实现对应的逻辑&…

亚马逊云服务器Amazon EC2

一、什么是Amazon EC2? Amazon Elastic Compute Cloud (Amazon EC2) 在 Amazon Web Services (AWS) 云中提供按需、可扩展的计算容量。使用 Amazon EC2 可降低硬件成本,让您能够更快地开发和部署应用程序。您可以使用 Amazon EC2 启动任意数量的虚拟服务…

Word 右键内容不显示段落/字体问题解决

有时需要调整图片的行间距,但是右键图片所在行,没有段落的选项。 可以将焦点保持在图片所在行,然后点击右下角的图标。同理不显示字体也可以点击左边字体中的右下角图标。

学生公寓智能限电系统的功能和作用

学生公寓智能限电系统‌是一种用于管理和限制学生公寓用电的设备和技术,旨在确保用电安全、防止火灾事故,并促进节能减排。以下是关于学生公寓智能限电系统的详细介绍: 1、功能和作用 智能限电系统通过以下功能来管理和限制用电&#xff1a…

[IT项管理(双语)]项目的基本概念

什么是项目 1.1项目的定义 项目(project)是为了创造一个特定的产品,服务,或者成果而采用的临时性的努力。 项目 产出唯一 临时性 1.2运营的定义 运营(operation)是 为了维持业务而进行的工作。 Imp1.3运…

ASP.NET Core SignalR 双工通信

01. 介绍 🎯 ASP.NET Core SignalR 是一个开放源代码库,它简化了向应用添加实时 Web 功能的过程。 实时 Web 功能使服务器端代码可以在服务器上激发事件时将事件推送到连接的客户端。 使用 SignalR,客户端也可以将消息发送到服务器&#xff…

Sonar基于SonarQube统一产品命名,助力提升开发者体验,以及本地、云端或IDE端的代码质量与安全

日前,领先的代码质量和安全解决方案提供商Sonar宣布,将围绕SonarQube简化其现有的产品命名。 作为Sonar的旗舰品牌,SonarQube代表了公司的核心使命:提高所有代码的质量和安全性,同时提供更好的开发人员体验。这些变化…

搭建高可用负载均衡系统:Nginx 与云服务的最佳实践

搭建高可用负载均衡系统:Nginx 与云服务的最佳实践 引言 在项目开发过程中,我们通常在开发和测试阶段采用单机架构进行开发和测试。这是因为在这个阶段,系统的主要目的是功能实现和验证,单机架构足以满足开发人员的日常需求&…

芯科科技突破性超低功耗Wi-Fi 6和低功耗蓝牙5.4模块加速设备部署

致力于以安全、智能无线连接技术,建立更互联世界的全球领导厂商Silicon Labs(亦称“芯科科技”,今日宣布推出SiWx917Y超低功耗Wi-Fi 6和低功耗蓝牙(Bluetooth LE)5.4模块。 作为成功的第二代无线开发平台的新产品&…

CentOS7虚拟机 网络适配器 NAT模式和桥接模式区别

一、环境介绍 宿主机:Windows电脑 虚拟机:VMware下的CentOS7 局域网:路由器下的各真实主机组成的网络 内部局域网:宿主机构建的一个内部网路 二、NAT和桥接网络链接模式区别 NAT模式:相当于宿主机构建一个内部局域网&a…

【AIGC半月报】AIGC大模型启元:2024.12(上)

【AIGC半月报】AIGC大模型启元:2024.12(上) (1)OpenAI-12日发布会(持续更新中........)Day01-12.06:o1满血版上线(已发布)Day02-12.07:强化微调&a…

开源堡垒机JumpServer配置教程:使用步骤与配置

开源堡垒机JumpServer配置教程&#xff1a;使用步骤与配置 上一篇文章星哥讲了如何安装JumpServer堡垒机&#xff0c;本篇文章来讲如何配置和使用JumpServer。 安装成功后&#xff0c;通过浏览器访问登录 JumpServer 地址: http://<JumpServer服务器IP地址>:<服务运…

gulp应该怎么用,前端批量自动化替换文件

背景 最近公司准备把所有项目中用到的国际化相关的key规范化&#xff0c;原因是: 一直以来公司的app和web端 在针对相同的需求以及相同的国际化语言&#xff0c;需要设置不同的两份国际化文件&#xff0c;难以维护旧版的国际化文件中&#xff0c;存在的大量值重复&#xff0c…

【5G】5G Physical Layer物理层(一)

5G多址接入和物理层与长期演进&#xff08;LTE&#xff09;存在一些差异。在下行方向&#xff0c;5G与LTE相似&#xff0c;依旧采用正交频分多址&#xff08;OFDMA&#xff09;。而在上行方向&#xff0c;5G采用了OFDMA和单载波频分多址&#xff08;SC-FDMA&#xff09;&#x…

Docker 安装 中文版 GitLab

Docker 安装系列 安装GitLab、解决服务器内存不足问题、使用域名/IP地址访问项目 1、拉取 [rootTseng ~]# docker pull twang2218/gitlab-ce-zh:latest latest: Pulling from twang2218/gitlab-ce-zh 8ee29e426c26: Pull complete 6e83b260b73b: Pull complete e26b65fd11…

力扣-图论-4【算法学习day.54】

前言 ###我做这类文章一个重要的目的还是给正在学习的大家提供方向和记录学习过程&#xff08;例如想要掌握基础用法&#xff0c;该刷哪些题&#xff1f;&#xff09;我的解析也不会做的非常详细&#xff0c;只会提供思路和一些关键点&#xff0c;力扣上的大佬们的题解质量是非…