首页   注册   登录
hanshijun

hanshijun

V2EX 第 319220 号会员,加入于 2018-05-29 01:48:46 +08:00
今日活跃度排名 21823
1 G 17 S 73 B
猫奴学编程:到底什么是“抽象”和“面向对象”
  •  1   
    Java  •  hanshijun  •  2 天前  •  最后回复来自 NorthBigPenguin
    3
    一个网络请求的冒险之旅
  •  1   
    推广  •  hanshijun  •  281 天前  •  最后回复来自 hanshijun
    15
    假如有一天,人工智能用于相亲
    生活  •  hanshijun  •  342 天前  •  最后回复来自 FrankBai
    6
    对微信的一点随感
    微信  •  hanshijun  •  2019-01-18 13:30:42 PM  •  最后回复来自 May725
    5
    考研进行时
    生活  •  hanshijun  •  2018-12-23 19:09:42 PM  •  最后回复来自 whwq2012
    31
    请问本科毕业设计做什么好呢?
  •  1   
    程序员  •  hanshijun  •  104 天前  •  最后回复来自 CEBBCAT
    77
    云上秘史 第一章 : 缘起 HBase
    编程  •  hanshijun  •  2018-12-08 13:49:23 PM  •  最后回复来自 echisan
    8
    软件与墨菲定律
    软件  •  hanshijun  •  2018-11-20 13:12:07 PM  •  最后回复来自 noNOno
    1
    hanshijun 最近回复了
    正文:

    我是一只来自乡下的小猫,因为出生时发出了“**啾啾**”的声音,加上铲屎官实在是太懒了,所以他就给我取名“啾啾”。

    这是我来上海打工的第一年,听大家说现在互联网行业比较好,工资比价高,所以我也加入了学习编程的队伍。不过我好像比较笨,很多问题都要复习多遍才能理解,所以我把他们都记录在这里。

    这是我在 2020 年的第一篇笔记,大家多多指教呀。

    ![image]( https://imgur.com/omDfDLM)


    在学习编程的开始,我就遇到了一个问题。我看很多人都在说“要对问题进行抽象”、“结合面向对象的编程思想”,那到底什么是“抽象”,什么是“面向对象”?好在我的铲屎官寒食君就是一名程序员,所以我就“不耻下问”了。

    ![image]( https://imgur.com/RIi0yp3)


    ![image]( https://imgur.com/lUmAvcT)



    **1\. 什么是抽象?**

    这是一个好问题,程序员们都在说**抽象**,但是新人一头雾水,到底什么才是抽象?按照我个人的理解,当你遇到一个问题,你能将其中的关键信息提取出来并进行建模,就是“抽象”。

    还是不好理解?比如“汇编语言是对底层机器的轻微抽象”,因为机器底层都是二进制,对于人来说,使用二进制来编程实在太反人类了,于是就有人对底层机器指令进行封装,发明了汇编语言,相比纯二进制,它的可读性强多了。但是它依然太难了,于是就渐渐出现了命令式语言,接着出现了高级语言,直到现在大部分程序员通过写英文就能够来命令机器如何运行。

    ![image]( https://imgur.com/LofORrG)



    ![image]( https://imgur.com/oP0YR6l)



    **2\. 如何进行抽象?**

    “所有的编程语言都提供抽象机制。可以认为,人们能够解决的问题的复杂性直接取决于抽象的类型和质量。”

    换句话说,写代码之前,先好好思考,不要抄起键盘猛如虎,一看 bug 二百五。磨刀不误砍柴功,这就是设计阶段。比如上面提到的汇编语言,它依然是基于计算机的结构来设计的,当你使用它时,你就要强行将自己的脑回路变成计算机的电路来思考。这是比较困难的,这也是为什么现在很多人都觉得写汇编语言的都是大佬。但是缺点是,这样的程序不仅难写,而且维护起来也很难。

    所以今天我们要说的主题就是一种更符合人类思维的**抽象方式**:面向对象。

    虽然随着时代的发展,面向对象的一些缺陷显露出来,也遭到了一些人的抨击,但我个人认为这依然无法阻碍其成为最伟大的编程思想之一,它依然是强有力的生产方式。相较于某些只能解决特定类型问题的抽象方式,面向对象是通用的,它将所有事物都视为 Object,这和现实世界一一对应,所以一每一个现实世界中的问题都能映射到程序中。

    ![image]( https://imgur.com/vp33Cyz)



    **3\. 那到底什么是面向对象?**

    SmallTalk 是第一门成功的面向对象语言,Java 是最成功的一门面向对象语言。Alan Kay 总结了这五条**面向对象**的法则,我们一起来理解一下。

    * 万物皆为对象

    你可以将现实生活中的任何事物都看作是(抽象为)一个对象( Object ),对象的特点是:拥有自身的属性行为能力。

    * 程序是对象的集合,他们通过发送消息来告知彼此所要做的

    对象和对象之间不是完全独立的,他们可以通过互相发送“消息”来沟通。对象既然拥有行为能力,那么他们可以为其他对象做一些事,前面指的“发消息”,事实上就是指对对象的方法的调用。

    * 每个对象都有自己的由其他对象所构成的存储。

    每个对象都可以包含其他对象,比如“汽车对象”可以包含“轮子对象”。这样就能够通过包含关系来构建复杂的体系,比如你需要构建“火箭对象”,那必然是各个系统对象的组合,各个系统对象又是由更小的模块对象组成的。

    * 每个对象都拥有其类型

    这个很好理解,万事万物都有其类型,比如我们人类就是一个“类型”。编程语言中通常用 class 来定义类型。

    * 某一特定类型的所有对象都可以接收同样的消息。

    这句话可能有点难理解,什么是“某一特定类型的所有对象”?这就是“多态”,举个最通俗的例子,啾啾你是“美短”类型的猫,奶泡是“布偶”类型的猫,美短类型和布偶类型都属于猫类型,所以你们都属于猫类型,你们都拥有“猫类型”的属性和行为能力,听懂了吗?关于”多态“,下文会详细讲到。

    总结来说,对象具有属性和方法。

    ![image]( https://imgur.com/PLzu1tb)



    ![image]( https://imgur.com/B3enJUT)



    ![image]( https://imgur.com/MJzaGti)



    **4\. 为什么要有面向对象?**

    因为程序员可以通过定义类来更快、更容易地抽象问题,程序员可以自由地创建新的数据类型来对问题进行建模,而不用只能通过计算机现有的、机器中基本存储单元来解决问题。

    依赖其他编程思想也能够构建仿真程序,但是面向对象能够更容易更高效地降解问题。但是面向对象不是想象的那么简单,如何对现实问题与程序建立合理优雅的映射依然是设计的难点。

    这里就不得不引出面向对象的三大特性:**封装**、**继承**、**多态**。

    ![image]( https://imgur.com/IwmTJaN)



    **5\. 三大特性:****封装、继承、多态**

    这三个词很多人可能都已经烂熟于心了,如果面试被问到,已经能够达到条件反射,脱口而出的地步。但假如面试官让你深入聊聊,还能够保持自信吗?如果开始眼神躲闪,语无伦次,那基本凉凉,因为这是比较基本的问题,很能够看出一个人对基础的掌握程度,所以当啾啾你要学编程时,我首先要把这些告诉你听。

    * **封装**

    关于封装,上面也已经提到了,当我们创建一个“类”我们就需要定义它的属性和方法。属性代表它“有什么”,方法代表它“能做什么”。将它们“封装”到一起,就成为了一个类,按照这个类,我们可以构建对象。

    此外,类的属性和方法也是拥有权限等级的,分为 public、private、protected,具体三者代表什么意思,这里不赘述了,不了解的小伙伴可以去查些资料。

    因此,由类构建的对象只向其他对象暴露开放的属性和方法。这是有好处的,假如你设计了一个类或一组程序构件开放给他人使用,这就能够进行访问控制,第一,他们不能随心所欲地篡改,或者由于疏忽修改你的代码,他们只需要关心那些对他们开放的内容;第二,当你进行了内部修改,只要不改变对外接口,对其他调用方则是无感知的,他们不用修改相应旧代码,保证了稳定和效率。

    更重要的,也是很多人忽视的。一个类如果封装得好,那么它将拥有很高的“内聚性”,什么是内聚性?高内聚代表它只完成自己该做的事,不涉足和自己无关的事,作为代码构件,很容易被重用,能有和其他构件很容易地组合,以发挥更大的能力,高内聚常常意味着代码质量。

    * **继承**

    在讲完封装之后,你应该对“类”、“对象”有了更深的认识。

    试想这样一种情况:假如已经有了一个类“猫”拥有了属性:四只爪子、两只耳朵、一条尾巴等多个属性,以及“喵喵叫”这样的方法。现在我想要创建一个“美短猫”的类型,那我还得重新新建一个类,再写一遍“四只耳朵”、“两只眼睛”...... 这显然太麻烦了。所以就出现了“继承”,即“美短猫”类型继承“猫”类型,获取父类型的全部属性和方法。此外,子类型可以新增属性,比如“灰白条纹”;以及新增方法,比如“擅长跑酷”,重写当前类中继承的方法。这时候,继承所描述的是**“is-a”的关系**,参照上例:美短猫 **is a** 猫。

    通过继承,既能体现两个相关对象的差异性,又能体现出相似性。清晰的类继承结构是非常重要的,一旦你的项目变得越来越大,不合理的继承关系会让你的代码臃肿并且难于拓展。

    理想化的继承是纯粹的,但是,并非所有的设计都是完美的。有时候,你不得不在子类中添加一些方法,而这些方法可能是非常独特,不够一般化的。举个很简单的例子,“多啦 A 梦”从外观和设定上来说,也应该继承“猫类型”,有拥有超能力,所以此时我们认为“多啦 A 梦” is like a “猫”,哆啦 A 梦像一只猫,这就是**“is like a”**关系。

    ![image]( https://imgur.com/B7gO2y5)



    * **多态**

    看到这里,是不是感觉有点渐渐复杂了起来?坚持一下,下面将进入面向对象最美妙的东西:多态。

    多态,这个名字听上去就很高大上啊,顾名思义就是多种状态,这里的状态指的就是”对象类型“。什么意思?有时候,我们在进行编程时,并不关心当前操作的具体是什么类型的对象。

    就像宠物店的员工在喂猫时,只关心自己喂的是猫,而不关心具体是什么猫。只有当真正喂食的时候,才根据具体猫的类型来喂不同的猫粮。这样,一旦宠物店引进了新品种的猫,该员工也不需要修改动作,只知道自己喂的是猫,具体怎么喂,到时候看猫的类型再说。如果将该员工视作是程序,那么无论宠物店引进什么品种,该程序都能完美兼容,不需要修改。

    这就是“多态”,程序操作的是一个泛化的基类,在编译期,编译器只能确保被调用方法的存在,以及类型检查,但是不知道该方法究竟会调用哪个具体方法,执行哪段具体代码,直到运行时,才能根据对象的具体类型来作出判断,执行相应的代码,这就是“后期绑定”的概念。

    如果你还是有点不太明白,我们再来温习下上面的例子。假如喂猫员工是个程序,程序员不必写这样的代码“如果遇到美短,喂这种猫粮;如果遇到布偶,喂这种猫粮;如果遇到机器猫,喂铜锣烧...”这样写一定不是一个好程序员,不仅非常繁琐,而且种类是穷举不完的。程序员只要做的是告诉这个程序“你要知道喂的是猫,具体喂什么,等这只猫来了再决定吧”,这就给编程带来了极大的灵活性。

    这么一说,是不是瞬间明白了?多态就是这么简单,但也是这么奇妙。


    ![image]( https://imgur.com/kSdUaK5)
    104 天前
    回复了 hanjingzhan 创建的主题 职场话题 你们实习的时候怎么熬过来的。
    实习时感到很快乐...导致大四一年都没回学校...
    115 天前
    回复了 drupal 创建的主题 问与答 关于礼节问题
    楼主扫射范围太大了,想问一下这几个月面了多少人,90 后占比多少,没礼貌的 90 后又占比多少
    118 天前
    回复了 TristanYang 创建的主题 分享创造 喜欢中国风的 V 友可以进来看看...
    好看
    281 天前
    回复了 hanshijun 创建的主题 推广 一个网络请求的冒险之旅
    @nosky https://jihangyu.com/ 有段时间没更新了
    281 天前
    回复了 hanshijun 创建的主题 推广 一个网络请求的冒险之旅
    @lhx2008 感谢指出
    281 天前
    回复了 hanshijun 创建的主题 推广 一个网络请求的冒险之旅
    @misaka19000 随便写写,应该也还有人不懂或者有些模糊(°ー°〃)
    281 天前
    回复了 hanshijun 创建的主题 推广 一个网络请求的冒险之旅
    @nanaw 因为我不想全盘否定微信,我认为公众号是一个不错的创作平台
    关于   ·   FAQ   ·   API   ·   我们的愿景   ·   广告投放   ·   感谢   ·   实用小工具   ·   1478 人在线   最高记录 5168   ·     Select Language
    创意工作者们的社区
    World is powered by solitude
    VERSION: 3.9.8.3 · 30ms · UTC 17:15 · PVG 01:15 · LAX 09:15 · JFK 12:15
    ♥ Do have faith in what you're doing.