小林静華
小林の小站

浅谈我对面向对象编程的理解

bookmark_border开发 | access_time2021年4月10日 | library_books3111字

写在前面·契机

昨天和一位不太擅长编程的同学交流编程问题,意外地发现自己虽然代码经常出问题,但编程思维还算可以。

虽说还可以,一直都觉得自己写代码时候的思路都很清奇,甚至有受到自己绘画和写作的影响(这些经历似乎也确实让我能从不同的角度考虑一个问题)。但我觉得总的来讲,缘由还是我写的第一个像样的程序就使用了类似面向对象编程的操作。

高二的时候生物在学进化,突发奇想想写一个兔子吃草进化的模拟,学了几周c++居然还真写出来个不错的程序。本来还想再加一层狐狸吃兔子以及随机生成地形,但由于学业繁重(划掉)自己太能咕了一直没有做。

本文将尝试以一种不太涉及代码本身,而是以编程思维的角度来浅谈我对面向对象编程的理解。下面折叠的内容又臭又长,是对面向对象编程中几个重要概念的介绍。

https://note.youdao.com/yws/api/personal/file/WEB64870c4d2418f6a7c18bba6ce8c3511b?method=download&shareKey=64a8630ebb7f76d5d4ee4e5ff47cdc52
橙色点是兔子 绿色点是草

一些并没有什么必要了解的概念

tl;dr

keyboard_arrow_down

那么问题来了,什么是面向对象编程?当年从网上看教程的时候,面向对象是放在封装里面的,我就想,哦嚯,封装,前端的东西,还是改天再学罢。但实际上它跟前端没多大关系。 为了更好的写这部分我甚至深夜去翻了最近编程课程的ppt。大概还是这种思想对我来说太过于自然了以至于一时间想不出来它究竟有什么特点。

它确实很自然

面向对象编程是与面向过程编程相对的一种编程架构,当后者纠结于更加抽象的内容的时候,前者则是以一种高度模拟人类的思维和人类与世界进行交互的方式来进行编程。生而为人,不是计算机,真是抱歉。这自然会带来一系列好处和坏处,这个在介绍完以下三个特点后再进行讨论。

封装性

我们就拿一个人举例子。封装性就是指,作为一个人,你的身高你的体重你的性别等等等等,都是包含在你这个人里面的,别人可以观察到你的一些属性,你也可以告诉别人你的一些属性。不会说你是男是女是写在你旁边的地面上,不看这块毫不相干的地面是没法知道你性别的。除此之外,你的身高肯定别人一看就能看个大概,但像社交网络账号这种东西可能就是一个比较隐私的东西,必须得你告诉别人别人才知道。这种开放性和隐私性也是封装性的一部分。

继承性

虽然说学生究竟是不是人这件事还有待商榷,但我们先假设,学生是人,那么只要是人能干的事学生都能干。这就是继承的一个大致概念了。
具体来讲有很多种情况,在此不一一赘述。

多态性

看着这个名字我想了半天,一看下面overload override才想起来,哦,原来是昨天,我没认真听课,光听见多态的内容没听见多态这两个字。
我更愿意称之为定义或者自定义。这个和继承也有点联系,比如说,一个人去吃饭,可能就很悠闲地去吃,你学生不一样,学生得抢饭,得干饭(我至今不懂什么叫干饭)。虽然都是要做吃饭这件事,但实际进行的操作又不太一样,这就是多态。


下面是之前提到的,面向对象编程的优点和缺点

The Good

  • 可以很轻松地思考交互。很简单,把自己想象成某个东西,要对另外某个东西进行什么操作,虽然很怪,但只要用脑子去想,还是能想出来的。
  • 封装性使得一切都井井有条。你的东西是你的,我的东西是我的,我们可以相互交流,但谁的东西是谁的一直很清楚。
  • 继承和多态让很多东西变得很容易懂,也很容易操作。假设学生也是人,那只要人能干的学生都能干,不过干的方式可能比较独特。

The Bad

  • 人脑还是有它的局限。面向对象编程优化起来没有那么轻松,体积庞大不说,运行效率也不会有那么高。
  • 井井有条的同时也多了很多规则,某些骚操作是直接不被允许的,各个对象之间的也需要留一些接口,这会逐渐让程序变得臃肿起来。
  • 安全性会存在问题。这个实在不太好解释,但一个庞大的系统确实不会好维护。

还是不太懂?下面还有几个比较重要的概念。

类 · Class

就是一类事物。比如人,人会有一些属性,比如身高体重性别,人还会有一些方法(就是能干什么),比如吃饭睡觉。

对象 · Object

就是某一个事物。比如一个人,一个人就有确定的身高体重,确定的吃饭或者睡觉的方式。

接口 · Port

就是访问一个对象某些属性的方法。比如你把自己的社交媒体账号写在小纸片上,这个小纸片就是访问你社交媒体账号的接口。你把这个纸片交给别人,他们才能知道你的社交媒体账号。


呼,tldr的部分终于写完了,希望能有所帮助。

面向对象编程的独特之处

与其说叫面向对象编程,所谓object oriented programming其实可以直译为绕着对象编程。每一个东西都是对象,它们都会不断地问类似于「我是谁?我在哪?我要干什么?」的问题,和其他的对象进行不断的交互,以达到程序的目的。

下面将按照我通常写游戏的工作流程,以经典游戏吃豆人中的内容为例浅谈面向对象编程。

万物皆对象

以一个完全的面向对象编程的操作去编一个吃豆人的话,游戏中几乎每一个东西都会被编成类和对象。

吃豆人是一个对象,每个豆是一个对象,鬼是对象,墙是对象,甚至如果需要的话游戏中的每一个格子都可以是一个对象。

但更为重要的是,游戏本身也是一个对象。

这是一个更为整体的东西,游戏本身的设置需要存在这样的一个对象中,例如地图的长和宽、豆或者鬼的数量、玩家的分数、游玩时间等等一些较为全局的东西,可以放在这样的一个对象之中。

游戏的渲染和显示通常需要依靠特定包中的引擎,一般情况下这也会是一个对象,使用的语言和包不同具体也会不同。

实例化/初始化 · 我是谁?我在哪?

这是必不可少的一步。一开始是不存在对象的,只有类的声明。我只知道一个鬼应该具有什么属性,但并没有鬼的对象,这时候就要根据需求去声明一个鬼的对象,这个由类创建对象的过程就是实例化,解决了「我是谁」的问题。把每个鬼相应的数据填进去,比如它在哪个位置,下一步要往哪边走,就是对这个对象的初始化,解决了「我在哪」的问题。

对游戏设置和渲染引擎对象的初始化极为重要,通常会被单独放进一个init()函数里面。init是initialize(初始化)的习惯简写方法

对象通过方法和接口进行交互 · 我要干什么?

这是程序的主要部分。刚才有提到,达到程序目的的过程就是各种对象相互进行交互。

一个吃豆人,假如它要向左走,就会调用自己一个名为「向左走」的方法,然后它就会通过和地图进行交互,得知自己左边是什么。如果是墙,那就走不动;如果是豆,那就把豆吃掉;如果是鬼,就被鬼吃掉,等等操作。吃掉豆的时候,会和在这个位置的具体这个豆进行交互,把它从地图上移除掉,也会与游戏设置进行交互,给玩家加分。

吃豆人中还有「大力丸」这个东西,当吃豆人吃掉「大力丸」后,便会与鬼进行交互,告诉鬼「你可以被我吃掉了」,鬼就会改变自己的运行模式,变成向吃豆人反方向逃跑,自己的速度和颜色也会变化。

这样就解决了「我要干什么」的问题。

模块化的结构

由于类和各自方法的使用,面向对象编程写出来的代码会变得高度模块化。

一个简单的游戏的main函数大概会简单到像下面这样:

init()
while (!fail()):
    game()

其中init()是对整个游戏的初始化,包括游戏设置、渲染和游戏中的各个对象。

下面的while循环通常被称为游戏主循环(Game Loop),里面的fail()是判断游戏结束的条件。这个条件有时也会写在while循环内部。

每一次循环通常被称为一个游戏循环(Game Cycle),中间的game()就是在每次循环中要进行的各种操作,也就是各个对象之间的交互,通常会涉及到对所有对象的遍历和固定的方法。

写在后面 · 结语

怎么样,你学废了吗?会写吃豆人了吗

尽管尽力去避开了代码相关的内容,本文对于对编程没有什么了解的人来讲依然不是很友好。但无论如何,「面向对象」这样的一个思维依然是人人都能掌握的、使用起来非常轻松和方便的东西。

希望本文对你能有所帮助!

封面图像源自steam商店PAC-MAN 256

小林 静華

文章作者

发表评论

textsms
account_circle
email

小林の小站

浅谈我对面向对象编程的理解
本文将尝试以一种不太涉及代码本身,而是以编程思维的角度来浅谈我对面向对象编程的理解。
扫描二维码继续阅读
2021-04-10