面向对象修炼手册(二)(消息与继承)(Java宝典)

🌈 个人主页:十二月的猫-CSDN博客
🔥 系列专栏: 🏀面向对象修炼手册

💪🏻 十二月的寒冬阻挡不了春天的脚步,十二点的黑夜遮蔽不住黎明的曙光 

目录

前言

消息传递

1 基本概念

1.1 概念

 2 消息表达式

3 消息机制特性

4 java中的消息传递

动/静态类型语言

1 动态类型语言

2 静态类型语言

3 区别与联系

伪变量 

继承

1 子类与父类

1.1 子类与父类的关系限制

1.2 子类与父类的替换原则

1.3 改写(重写)(覆盖)

1.4 继承形式

1.4.1 特化继承

1.4.2 规范继承

1.4.3 构造继承

1.4.4  泛化继承

1.4.5  扩展继承

1.4.6  限制继承

1.4.7  变体继承

1.4.8  合并继承

1.5 构造函数在继承中

1.5.1 构造函数的调用

1.5.2 构造函数的继承

1.5.3 子类与父类的构造函数

1.5.4 子类、父类构造例题:

总结


前言

上文介绍了类和对象的基础概念,然后深入研究了面向对象编程这个词语的深层含义。

简单复习一下:

面向对象方法的本质:

  • 找代理
  • 消息传递给代理
  • 代理解决问题
  • 我的问题就解决了

面向对象:只关注对象,不关注过程;对象包括:对象和实例对象

对于C语言这种面向过程的语言,在编程中,程序员关注的重点是过程、是解决问题的方法、是一个个函数

面向对象语言,在编程中,程序员关注的重点转变为对象

面向对象编程:通过对象间的消息传递解决任务,完成编程

编程的目的是解决问题;

面向过程的语言直接关注解决问题的方法解决问题

面向对象的语言关注解决问题的对象,通过消息传递解决问题

本篇重点来讲消息机制继承

消息机制:细心的小伙伴应该已经发现:消息机制上节课就已经提到过了!没错,消息机制就是面向对象编程中实现相应功能的方法(面向对象编程完成功能都靠对象,而对象完成功能需要消息的传递)。没有消息传递,再有手段的对象也无法完成功能(因为它压根不知道要完成什么功能、有什么要求)

继承:继承自然也是非常重要的。面向对象编程有许多的优点,其中最重要的一点就是代码复用,能够重复使用一段完成特定功能的代码。进一步思考:为什么代理人解决就比全部自己解决更容易?深层次的原因在于:使用代理人解决问题,代表这一类的问题都可以用代理人来解决,不需要每次换算法都要从头实现每一个方法(代码复用性很好)。

继承作为C++三大特性之一,其就体现了代码复用的思想(例如:男人、女人都继承自人类,那么男女人都有作为人的特征。因此男女人编程时可以直接使用人中的特性和方法,不需要改动原本的代码细节(仅仅加入人这一类的各个方法接口即可)

消息传递

消息传递:一个对象通知另一个已经完成声明的对象需要进行的特定行为的机制

本质:调用一个类的方法,在方法中给需要传递的形参

1 基本概念

1.1 概念

对象间相互请求相互协作完成某一任务的途径

  • 对象接收多个消息,响应不同
  • 同一消息给多个对象,响应不同

 2 消息表达式

  1. 消息接受者:消息传递的目的函数,消息的接受对象
  2. 消息选择器:消息传递系统中的过滤器,用于让消息接收者接受并处理特定性的消息
  3. 参数(消息内容) :实际传递给接收者的信息(需要经过选择器的过滤和限定)

3 消息机制特性

封装:

封装把一个对象的属性私有化,同时提供一些可以被外界访问的属性的方法。保护类受到不必要的修改

解耦合:

解除了消息发送者对任务完成过程的耦合,消息发送者不需要具体知道任务是如何完成的。仅仅需要负责发送消息并等待消息接收者的响应即可

消息传递中的重点概念辨析:

1、消息发送的对象是:消息接收器

2、消息接受器过滤后送给消息接收者

3、过程调用是非面向对象编程中的复用方法,其没有接收器

4、 响应消息所执行的行为并不是一成不变的,他们根据接收器类的不同而不同。(响应行为随接收器不同而不同) 

4 java中的消息传递

aCard.flip ();
aCard.setFaceUp(true);
aGame.displayCard(aCard, 45, 56);

/静态类型语言

动/静态类型语言的区别就在对于:变量类型是动态的还是静态的

动态:在运行时绑定

静态:在编译时绑定 

1 动态类型语言

定义:数据类型是动态的(动态绑定、运行时绑定、自动匹配)

  • 类型的检查是在运行时做的;
  • 变量不需要声明类型,程序在运行时自动确定
  • 优点是方便阅读
  • 缺点是不利于调试

2 静态类型语言

定义:数据类型是静态的(静态绑定、编译时绑定、人工分配)

  • 类型检查是编译时确定
  • 变量需要明确类型
  • 优点是结构规范,利于调试
  • 缺点是代码不够简洁

3 区别与联系

  • 动态类型语言与静态类型语言之间的差异在于变量或数值是否具备类型这种特性。
  • 静态类型语言在编译时做出内存分配,动态类型语言在运行时才分配内存

伪变量 

大多数面向对象语言中,接收器并不出现在方法的参数列表中,而是隐藏于方法的定义之中。只有当必须从方法体内部去存取接收器的数值时,才会使用伪变量(pseudo-variable)

Java,C++:this

伪变量在使用时就好像作为类的一个实例

在理解上应该认为this是:接收器留给所有选择器的接口

Java:构造函数中,使用this区分参数和数据成员

public class ThisTest {private int i=0;//第一个构造器:有一个int型形参ThisTest(int i){this.i=i+1;//此时this表示引用成员变量i,而非函数参数iSystem.out.println("Int constructor i——this.i:  "+i+"——"+this.i);System.out.println("i-1:"+(i-1)+"this.i+1:"+(this.i+1));//从两个输出结果充分证明了i和this.i是不一样的!}
}

继承

1 子类与父类

1.1 子类与父类的关系限制

  • 子类实例拥有父类的所有数据成员。(私有成员变量也会拥有,但是无法访问)
  • 子类的实例必须至少通过继承实现父类所定义的所有功能

1.2 子类与父类的替换原则

指如果类B是类A的子类,那么在任何情况下都可以用类B来替换类A,而外界毫无察觉(这里强调的是语法上可行,和里氏替换原则有一定的重合)

这里的子类是指符合替换原则的子类关系(形式上继承,行为上也继承

1.3 改写(重写)(覆盖)

子类有时为了避免继承父类的行为,需要对其进行改写

语法上:子类定义一个与父类有着相同名称且类型签名相同的方法

运行时:变量声明为一个类,它所包含的值来自于子类,与给定消息相对应的方法同时出现于父类和子类

改写发生下的实际调用: 

改写发生在:

1、父子类之间

2、同姓名、同标签方法上

1.4 继承形式

继承的目的就是复用代码,但是继承的形式存在区别,存在:1、特殊化;2、规范化;3、构造化;4、泛化两种类型

1.4.1 特化继承

很多情况下,都是为了特殊化才使用继承。在这种形式下,新类是基类的一种特定类型,它能满足基类的所有规范。 用这种方式创建的总是子类型,并明显符合可替换性原则。与规范化继承一起,这两种方式构成了继承最理想的方式,也是一个好的设计所应追求的目标。
例如:
从马派生出白马:从抽象的马,到具有具体颜色(白色)的马,增加了颜色这个属性。
从人派生出男人:从抽象的人,到具有具体性别(男性)的人,增加了性别这个属性。

1.4.2 规范继承

规范化继承用于保证派生类和基类具有某个共同的接口,即所有的派生类实现了具有相同方法界面的方法。基类中既有已实现的方法,也有只定义了方法接口、留待派生类去实现的方法。派生类只是实现了那些定义在基类却又没有实现的方法

在Java中,关键字abstract确保了必须要构建派生类。声明为abstract的类必须被派生类化,不可能用new运算符创建这种类的实例。除此之外,方法也能被声明为abstract,同样在创建实例之前,必须覆盖类中所有的抽象方法。规范化继承可以通过以下方式辨认:基类中只是提供了方法界面,并没有实现具体的行为,具体的行为必须在派生类中实现。GraphicalObject没有实现关于描绘对象的方法,因此它是一个抽象类。其子类Ball,Wall和Hole通过规范子类化实现这些方法

最理想的继承:特殊化继承、规范化继承

1.4.3 构造继承

一个类可以从其基类中继承几乎所有需要的功能,只是改变一些用作类接口的方法名,或是修改方法中的参数列表

即使新类和基类之间并不存在抽象概念上的相关性,这种实现也是可行的

例如:

树-独木舟 保留了材质等属性,修改了形状的属性

堆栈-队列 修改了pop() push()等方法,栈顶和栈底变成了队首和队尾

写二进制文件-写学生信息文件

当继承的目的只是用于代码复用时,新创建的子类通常都不是子类型(违反里氏替换原则)。这称为构造子类化。一般为了继承而继承,如利用一些工具类已有的方法

1.4.4  泛化继承

派生类扩展基类的行为,形成一种更泛化的抽象。不完全等同于特殊化继承的反面。是从基类扩展一部分行为,形成更加泛化的抽象。在程序中表现为对原来存在的功能进行修改或者扩展

子类对基类功能进行修改、拓展。其功能的范围比基类更大,并不一定包含。因此不符合可替换原则

可替换原则: 

  1. 子类可以实现父类的抽象方法,但不能覆盖(改写)父类的非抽象方法。
  2. 子类中可以增加自己特有的方法。
  3. 当子类的方法重写父类的方法时,方法的前置条件(即方法的形参)要比父类方法的输入参数更宽松。
  4. 当子类的方法实现父类的抽象方法时,方法的后置条件(即方法的返回值)要比父类更严格。

前两者保证逻辑上可替换,后两者保证语法上可替换

从Window派生出了Colored_Window。
public Class Window{
...double size;setSize(){...}getSize(){...}
}
public Class Colored_Window extends Window{
...String color;setColor(String str){...};getColor(String str){...};
//扩展了查看颜色和设置颜色两个行为
}
1.4.5  扩展继承

如果派生类只是往基类中添加新行为,并不修改从基类继承来的任何属性,即是扩展继承。(泛化子类化对基类已存在的功能进行修改或扩展,扩展子类化则是增加新功能

由于基类的功能仍然可以使用,而且并没有被修改,因此扩展继承并不违反可替换性原则,用这种方式构建的派生类还是派生类型 

举例:学生(父类)、会弹琴的学生(子类)

1.4.6  限制继承

如果派生类的行为比基类的少或是更严格时(违反里氏替换原则),就是限制继承。

常常出现于基类不应该、也不能被修改时。

限制继承可描述成这么一种技术:它先接收那些继承来的方法,然后使它们无效

举例:双向队列-〉堆栈

1.4.7  变体继承

子类和父类之间都是对方的变体,可以任意选择两个之间的父子关系

举例:用为控制鼠标的代码与用来控制图形输入板的代码几乎完全相同。在概念上没有理由让一个类作为另外一个类的父类,因此可以选择任何一个类作为另外一个类的父类

1.4.8  合并继承

可以通过合并两个或者更多的抽象特性来形成新的抽象。

一个类可以继承自多个基类的能力被称为多重继承 

多重继承在java中是不允许的,因为一旦父类中有同名同签名方法则子类不知道该调用哪个方法

举例:助教

1.5 构造函数在继承中

1.5.1 构造函数的调用
  • 在构造实例对象时,由程序自动调用(隐式调用)
  • 由程序员主动调用:在子类构造方法中调用父类的方法
1.5.2 构造函数的继承
  • 构造函数不能被继承(子类和父类有自己的构造函数)
  • 构造函数只能通过两种方法获得:1、自己编写;2、系统默认生成
1.5.3 子类与父类的构造函数
  • 子类构造函数可以用super()主动调用父类的构造函数(调用必须在第一行完成)
  • 子类构造函数如果没有主动调用父类构造函数,则系统会主动调用父类构造函数
  • 如果系统调用super(),而父类中的super()并不存在,则报错
1.5.4 子类、父类构造例题:

题目一:

运行下面程序:

class SuperClass{private int n;SuperClass(){System.out.println("SuperClass()");}SuperClass(int n){System.out.println("SuperClass(int n)");this.n = n;}
}
class SubClass extends SuperClass{private int n;SubClass(){super(300);System.out.println("SuperClass");}    SubClass(int n){System.out.println("SubClass(int n):"+n);this.n = n;}
}
public class TestSuperSub{public static void main (String args[]){SubClass sc = new SubClass();SubClass sc2 = new SubClass(200); }
}

结果如下:

SuperClass(int n)
SuperClass
SuperClass()
SubClass(int n):200

题目二:

class A { A() { 
System.out.println("A"); 
}} 
class B extends A {B() {System.out.println("B"); } 
}class C extends B { C() { System.out.println("C");}} 
public class hrt { public static void main(String args[]) {new C();} 
}

运行结果:

输出
A
B
C

基类构造器总是在导出类的构造过程中被调用,而且按照继承层级逐渐向上链接(调用顺序则是从基类开始向下)。可以理解为,这么做的逻辑关系是在一个类构建时可能会用到其父类的成员、方法。在清理时顺序相反。

总结

本系列内容均来自:山东大学-潘丽老师-面向对象开发技术-课程ppt、《设计模式》、《大话设计模式》

如果觉得写的还不错,可以点个赞收藏一下呀~~

祝大家学业、事业、爱情顺利!

天天开心,没有Bug每一天

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

如若内容造成侵权/违法违规/事实不符,请联系多彩编程网进行投诉反馈email:809451989@qq.com,一经查实,立即删除!

相关文章

App推广告别邀请码,Xinstall助您一键触达海量用户!

在移动互联网高速发展的今天,App的推广与运营已成为每个开发者都必须面对的问题。然而,随着互联网流量的日益分散和用户需求的不断变化,传统的App推广方式已经难以满足现代市场的需求。尤其是在获取用户时,很多开发者还在采用传统…

动手学深度学习(Pytorch版)代码实践 -卷积神经网络-26网络中的网络NiN

26网络中的网络NiN import torch from torch import nn import liliPytorch as lp import matplotlib.pyplot as plt# 定义一个NiN块 def nin_block(in_channels, out_channels, kernel_size, strides, padding):return nn.Sequential(# 传统的卷积层nn.Conv2d(in_channels, ou…

图的学习.

目录 一、图的基本概念 1.1图的种类 1.2顶点的度、入度和出度 1.3边的权和网 1.4路径、路径长度和回路 二、图的存储结构 2.1邻接矩阵法 2.2邻接表法 2.3十字链表 2.4邻接多重表 三、图的遍历 3.1广度优先搜索 3.2深度优先搜索 四、图的应用 4.1最小生成树 4.1.…

VSCode 安装Remote-SSH

1、打开扩展商店安装Remote-SSH 快捷键:CtrlShiftX 2、配置ssh连接 打开命令面板(CtrlShiftP) 输入"Remote-SSH: Connect to Host"并选择。 输入你的Ubuntu服务器的IP地址或主机名。 3、连接到ubuntu服务器 如果是第一次连接&…

FPGA结构相关简介

一、芯片分类 ​FPGA属于数字芯片的一种,下面是根据世界半导体贸易统计协会WSTS的一个半导体分类,可以看到FPGA所属的类别。 二、FPGA的发展史 ​下图为FPGA的发展历史 三、FPGA的结构分类 下面是从三个角度进行划分 四、参考资料 《FPGA原理与结构》—…

【课程总结】Day10:卷积网络的基本组件

前言 由于接下来的课程内容将围绕计算机视觉展开,其中接触最多的内容是卷积、卷积神经网络等…因此,本篇内容将从卷积入手,梳理理解:卷积的意义、卷积在图像处理中的作用以及卷积神经网络的概念,最后利用pytorch搭建一…

构建未来应用的核心,云原生技术栈解析

🐇明明跟你说过:个人主页 🏅个人专栏:《未来已来:云原生之旅》🏅 🔖行路有良友,便是天堂🔖 目录 一、云原生技术栈 1、容器和容器编排 1.1 Docker 1.2 Kubernete…

ULTRAINTERACT 数据集与 EURUS 模型:推动开源大型语言模型在推理领域的新进展

在人工智能的浪潮中,大型语言模型(LLMs)已经成为推动自然语言处理技术发展的关键力量。它们在理解、生成语言以及执行复杂任务方面展现出了巨大的潜力。然而,尽管在特定领域内取得了显著进展,现有的开源LLMs在处理多样…

Vue3+ElementPlus+pinia 小案例

Vue3ElementPluspinia 小案例 1、初始化项目 使用脚手架快速创建Vue3应用:https://cli.vuejs.org/zh/ 脚手架自动整合了vue-router路由、ts、前端工程化等库; 安装脚手架工具 npm install -g vue/cli检测安装是否成功 vue -V创建项目: …

UnityShader——基础篇之UnityShader基础

UnityShader基础 UnityShader概述 材质和UnityShader 总的来说,在Unity中需要配合使用材质(Material)和 Unity Shader 才能达到需要的效果,常见流程为: 创建一个材质创建一个 Unity Shader,并把它赋给上一步中创建的材质把材质…

Android模拟器linux内核的下载,编译,运行,驱动开发测试

Android模拟器linux内核的下载,编译,运行,内核模块开发 1.下载适合Android模拟器的内核 git clone https://aosp.tuna.tsinghua.edu.cn/android/kernel/goldfish.git git branch -a git checkout android-goldfish-4.14-gchips 新建一个目录…

【2024最新版】Java JDK安装配置全攻略:图文详解

目录 1. 引言2. 准备工作2.1 **确定操作系统**2.2 **检查系统要求**2.3 **下载JDK安装包**3. 安装步骤(以Windows系统为例)4. 配置环境变量4.1 jdk配置验证4.2 **配置JAVA_HOME环境变量**4.3 **配置Path环境变量**4.4 验证jdk是否配置成功 5. 结语 1. 引…

机器学习周记(第四十四周:Robformer)2024.6.17~2024.6.23

目录 摘要ABSTRACT1 论文信息1.1 论文标题1.2 论文摘要1.3 论文引言1.4 论文贡献 2 论文模型2.1 问题描述2.2 Robformer2.2.1 Encoder2.2.2 Decoder 2.3 鲁棒序列分解模块2.4 季节性成分调整模块 摘要 本周阅读了一篇利用改进 Transformer 进行长时间序列预测的论文。论文模型…

浅析MySQL-基础篇01

目录 执行一条select语句,发生了什么? MYSQL执行流程是怎么样的? 第一步:连接器 第二步:查询缓存 第三步:解析SQL 解析器 第四步:执行SQL 预处理器 优化器 执行器 执行一条select语句…

Temu(拼多多跨境电商) API接口:获取商品详情

核心功能介绍——获取商品详情 在竞争激烈的电商市场中,快速、准确地获取商品数据详情对于电商业务的成功至关重要。此Temu接口的核心功能在于其能够实时、全面地获取平台上的商品数据详情。商家通过接入Temu接口,可以轻松获取商品的标题、价格、库存、…

Day15 —— 大语言模型简介

大语言模型简介 大语言模型基本概述什么是大语言模型主要应用领域大语言模型的关键技术大语言模型的应用场景 NLP什么是NLPNLP的主要研究方向word2vecword2vec介绍word2vec的两种模型 全连接神经网络神经网络结构神经网络的激活函数解决神经网络过拟合问题的方法前向传播与反向…

什么是REST API

1. 什么是RESTful API REST API,全称 Representational State Transfer,最初由计算机科学家 Roy Fielding 提出。 是遵循 REST 架构规范的应用编程接口(API),支持与 RESTful Web 服务进行交互。 又被称作 RESTful API…

深度神经网络——深度学习中的 RNN 和 LSTM 是什么?

引言 自然语言处理和人工智能聊天机器人领域许多最令人印象深刻的进步都是由 递归神经网络(RNN) 和长短期记忆(LSTM)网络。 RNN 和 LSTM 是特殊的神经网络架构,能够处理顺序数据,即按时间顺序排列的数据。…

《Python 机器学习》作者新作:从头开始构建大型语言模型,代码已开源

ChatGPT狂飙160天,世界已经不是之前的样子。 更多资源欢迎关注 自 ChatGPT 发布以来,大型语言模型(LLM)已经成为推动人工智能发展的关键技术。 近期,机器学习和 AI 研究员、畅销书《Python 机器学习》作者 Sebastian …

Mac M3 Pro 部署Trino-server-449

目录 1、下载安装包 2、解压并设置配置参数 3、启动并验证 4、使用cli客户端连接测试 1、下载安装包 官方:trino-server-449 CLI 网盘: server https://pan.baidu.com/s/16IH-H39iF8Fb-Vd14f7JPA?pwd3vjp 提取码: 3vjp cli https://pan.baidu.…