V2EX = way to explore
V2EX 是一个关于分享和探索的地方
现在注册
已注册用户请  登录
hanshijun
V2EX  ›  Java

猫奴学编程:到底什么是“抽象”和“面向对象”

  •  1
     
  •   hanshijun · 2020-01-13 12:23:24 +08:00 · 2446 次点击
    这是一个创建于 1813 天前的主题,其中的信息可能已经有所发展或是发生改变。

    图全挂了...

    @Livid 麻烦删除下此贴

    hanshijun
        1
    hanshijun  
    OP
       2020-01-13 12:40:16 +08:00
    正文:

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

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

    这是我在 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)
    pinews
        2
    pinews  
       2020-01-13 15:17:42 +08:00
    我对“面向对象”的理解

    函数式编程可以理解为过程编程,既输入条件,计算,输出结果。
    打个比喻,原始人,饿了就去打猎,渴了去河边喝水,困了回山洞睡觉。
    当然,现代人也是如此,即函数时编程处理的模型简单直接。

    面向对象编程可以理解为职能状态编程,即涉及的任务相对独立,又有不可分的联系。
    举个例子,你是一个酋长,饿了,你能够自己打猎,但是委托给专人负责伙食,敌人来了,你可以亲自上阵冲锋,也可以委托给专人负责打仗,洪水来了,你委托专人治水。
    但是问题在于,打猎的时候,敌人来了怎么办?治水的时候缺粮怎么办?当然你可以成立一个打猎保卫部门,从打仗里独立出来,也可以成立一个困难时期食物分配部门。
    但有些时候还不到必须独立的地步,只需要打猎部门将自己的状态传达给保卫部门,各部门需要共享一些信息以便行使原来不具有的功能。

    我们可以看到,最初编程的时候只有简单直接就足够,但随着编程的复杂,函数需要引用越来越多的参数去判断,又要将原来一个扩张的函数分解更独立的函数,函数传来传去都是几个相同的参数。
    这时候就像(变成)始祖鸟(的蛋)一样,虽然还是函数时编程,但已经体现了面向对象编程的特征。
    所谓面向对象编程语言,就是把由人类自己规划编程布局的任务独立出来,由编程语言完成,而人类只要使用 api 就好了。
    为什么要用面向对象编程?人类在解决问题的时候,要从实际出发,从大局出发,将任务分解后,如果有些事务时重复的,有联系的,从而专门的人处理专门的事情。比如有人专门研究语言的特性,创造更合适的语言,有人装早更合适的框架,有人开发扩展组件,有人创造新的应用领域。

    当然面向对象也不是万能的,固定的,因为人类组成了社会,独立个体仍然是千差万别的,有大量的需求是重复的,也有大量的需求是基础的,简单的,却又不同的,这时候人们会有两种办法,第一选择固定模式再退化,第二是从底层创新完善。

    比如 pwa 吧,网页应用,高级到搭积木的模式,连面向对象都跨过去了。
    NorthBigPenguin
        3
    NorthBigPenguin  
       2020-01-18 06:13:36 +08:00 via iPhone
    1、数学思维,抽象就是简化问题,就像你做一个数学题,总结了一个道理,叫做定理,这就是一个抽象,总结出一个公式,公式就是抽象出来的
    2、文学思维,抽象就是把一句啰嗦的话,总结成一个词语,一个字,精炼了就是抽象,比如我们的成语,就是一种抽象,你形容妹子很美,你说你好漂亮。好美啊,这脸蛋,这眼睛,这眉毛怎么这么好看,成语就是沉鱼落雁,闭月羞花,八个字抽象出了美
    关于   ·   帮助文档   ·   博客   ·   API   ·   FAQ   ·   实用小工具   ·   5416 人在线   最高记录 6679   ·     Select Language
    创意工作者们的社区
    World is powered by solitude
    VERSION: 3.9.8.5 · 36ms · UTC 08:51 · PVG 16:51 · LAX 00:51 · JFK 03:51
    Developed with CodeLauncher
    ♥ Do have faith in what you're doing.