设为首页收藏本站|繁體中文

Project1

 找回密码
 注册会员
搜索
查看: 4954|回复: 97
打印 上一主题 下一主题

[胡扯] 【用代码说话】#1.实例对象

[复制链接]

Lv5.捕梦者 (暗夜天使)

只有笨蛋才会看到

梦石
1
星屑
21641
在线时间
9415 小时
注册时间
2012-6-19
帖子
7118

开拓者短篇九导演组冠军

跳转到指定楼层
1
发表于 2016-7-17 01:17:02 | 只看该作者 |只看大图 回帖奖励 |倒序浏览 |阅读模式

加入我们,或者,欢迎回来。

您需要 登录 才可以下载或查看,没有帐号?注册会员

x
本帖最后由 喵呜喵5 于 2016-7-17 21:15 编辑

【前言】

现在的论坛已经基本上没有什么技术输出或者干货分享了,所以最近一段时间一直想正正经经写一个 RM 脚本教程来误人子弟,思考了很多形式很多主题,比如【RM 永远不会告诉你的那些 Ruby 知识】啦【如何一步一步用脚本实现某个简单的功能】啦【Try This,Not This】啦啥的,但是仔细去推敲的话又写不动了。今天看了这个帖子(https://rpg.blue/forum.php?mod=viewthread&tid=394657)忽然意识到很多人所谓的“能理解、修改脚本代码”实际上从 Ruby 的层面上来看简直惨不忍睹,技术讨论区已经没了,黑科技区则不适合发这些东西,思考再三,决定在水区开始一个不定期更新的连载,每次给出一段构造简单包含基础知识的 Ruby 代码,用代码说话,让人能够真正理解代码背后的逻辑,而不至于说出【我能改脚本,但是变量为什么前面要加@啊】这种让人啼笑皆非的话出来
当然,阅读我这个系列需要你拥有一定的脚本基础,这个脚本基础指的是:你至少应该知道代码是一行一行执行的吧?至少要知道比较是否相等用的是 == 赋值用的是 = 吧,大概就是这种类似 Ruby 语言的常识一样的东西

鉴于我自己学术不精,这个系列又完全是由我自己发起自己执行的,没有什么人来负责内容的校对,帖子包含的内容难免存在各种错误,所以如果诸位阅读者发现了什么纰漏请不吝指正
同时,由于帖子可能包含错误,我可能会直接编辑原帖内容进行修正,因此,请不要转载这些帖子的内容以免帖子中的错误在转载后给他人带来困扰,最最不济,转载烦请注明原帖地址,谢谢合作

那么,下面是这个系列的正文

【用代码说话】#1.实例对象



  1. class A
  2.   def m1
  3.     p 'foo'
  4.   end
  5. end

  6. a = A.new
  7. aa = A.new
  8. a.m1
  9. aa.m1
  10. p (a.object_id == aa.object_id)
复制代码

请不要借助任何代码执行工具,阅读上面的代码并思考,输出的结果是什么?
如果你对 Ruby 接触不深的话,这里给你提供一个简单的补充知识,object_id 可以看作是一个座位号,在你的程序中,如果两个东西的座位号是相同的,那么他们就是【完全相同】的,如果两个东西的座位号是不同的,那么系统就会把他们当成【不同的东西】来区别对待



作为一门完全面向对象的语言,这样一段代码也许是个不错的开始。关于面向对象、类、实例对象这三个术语,这里并不想对其进行过多描述性的解释,毕竟,一堆的编程语言,一堆的脚本教程里已经变着法子讨论过一遍了,又是学生又是猫又是汽车的,以我拙劣的描述水平估计再去解释也只会让你更加混乱,所以,用代码说话,在上面这段代码中
  • A 是类
  • a 和 aa 是对象,并且是 A 的实例对象
  • 使用 A 来定义 m1,使用 a 和 aa 来执行 m1 的这种写代码的方式就是面向对象的编程方式
(当然,从严格的意义上来看,上面这三条描述并不严谨)

有了以上几句话的基础,下面我们可以从头开始完整的分析一遍代码了,我们一起从上往下看一下
  • A 做出了一个声明,告诉电脑,自己是一个类
  • A 定义了一个 m1 方法,告诉电脑,执行 m1 方法要做哪些事情
  • a 做出了一个声明,告诉电脑,刚刚来了一个新来的实例,他是 A 的实例,你们以后叫一声 a 就能找到他!
  • aa 做出了一个声明,告诉电脑,刚刚来了一个新来的实例,他是 A 的实例,你们以后叫一声 aa 就能找到他!
  • a 说,我要执行 m1 方法!
  • aa 说,我也要执行 m1 方法!
  • 我们询问系统,a 和 aa 的座位号相同吗?

这段代码的输出结果是
  1. "foo"
  2. "foo"
  3. false
复制代码

为什么 a 说我要执行 m1,输出的是"foo"?
因为 a 是 A 的实例,A 规定了执行 m1 要输出 "foo"

为什么 aa 说我要执行 m1,输出的是"foo"?
因为 aa 是 A 的实例,A 规定了执行 m1 要输出 "foo"

那么,为什么我们询问系统 a 和 aa 座位号是不是相同的时候,系统告诉我们不是呢?
因为,a 做了声明:坐在 a 这个位置的是一个新来的实例!
aa 也做了声明:坐在 aa 这个位置的也是一个新来的实例!
系统一看,哟呵,来了两个新来的实例,那么给你们两个各自分配一个座位号你们待着吧
这就是实例的特点了,即使 a 和 aa 都是 A 的实例,他们所做的事情是完全一样的,但是,他们却在不同的座位上坐着,在系统的层面,他们是不一样的两个东西

而像是这种用类定义行为,用实例执行行为的编程方式正是面向对象的编程方式

作为实用主义者,你大概会问了,道理我都懂,但是面向对象有什么用呢?
想想看吧,假设主角进入了一个史莱姆的巢穴,正与 1 只史莱姆战斗,史莱姆的动作非常单调,只会随机执行下列行动中的其中一种
  • 防御
  • 攻击
请问,你打算如何写代码来实现这些这只史莱姆的逻辑呢?
——哦,不好,你发现敌人不止 1只史莱姆,而是 100 只史莱姆!
——哦,不好,你在和史莱姆战斗的过程中发现史莱姆的动作居然不是【防御】和【攻击】而是【防御】、【攻击】和【逃跑】
面向对象正是为了解决这样的问题,你不需要为这 100 只史莱姆都各自定义相应的行为,你只需定义一个史莱姆的类,然后让史莱姆实例执行史莱姆类定义的行为就好了。正因为所有的史莱姆实例都会忠实的执行史莱姆类所定义的行为,所以,只要改变史莱姆类的定义,所有史莱姆实例的行为都能立刻发生改变,这听起来可比重新给把100只史莱姆的逻辑都重写一遍好多了不是吗?

那么,最后,附上一个会让你对这次学到的内容感到有点混乱的恶作剧
  1. class A
  2.   def m1
  3.     p 'foo'
  4.   end
  5. end

  6. a = A.new
  7. aa = a
  8. a.m1
  9. aa.m1
  10. p (a.object_id == aa.object_id)
复制代码

如果无法理解上面这段代码的输出结果,那么,比较一下这段代码和最开始那段代码的不同,然后再考虑一遍吧
也许,你能在后续的帖子中学到更多关于这个恶作剧的细节?

评分

参与人数 17星屑 +1092 收起 理由
chenyilindzh + 10 前排表白!
超音速 + 30 虽然听不懂
冰水金刚 + 60 精品文章
威风镰鼬 + 15 学费拿去
英顺的马甲 + 280 这贴应该设成精华帖
有丘直方 + 1 我小气
Vortur + 45 塞糖
鑫の尘埃 + 60 触瞎
kklt + 10 精品文章
天使喝可乐 + 200 触瞎

查看全部评分

Lv3.寻梦者 (版主)

…あたしは天使なんかじゃないわ

梦石
0
星屑
2208
在线时间
4033 小时
注册时间
2010-10-4
帖子
10779

开拓者贵宾

2
发表于 2016-7-17 07:08:42 | 只看该作者
如果每个人心里都能理解这些东西的话,感觉世界会清净很多(x

实例对象的英语到底是 instance 还是 object

点评

sample 误  发表于 2016-7-31 22:44
实例 instance 对象 object 实例对象 instance object(  发表于 2016-7-17 13:48
instance吧  发表于 2016-7-17 11:37
回复 支持 反对

使用道具 举报

Lv4.逐梦者 (版主)

聪仔

梦石
0
星屑
6187
在线时间
3077 小时
注册时间
2013-12-26
帖子
3145
3
发表于 2016-7-17 07:46:07 | 只看该作者
史莱姆明明只会攻击和逃跑,不会防御...
聪聪全国第三帅...
他们都叫我【人赢聪】
我的RM能力雷达图:

回复 支持 反对

使用道具 举报

Lv1.梦旅人

梦石
0
星屑
125
在线时间
63 小时
注册时间
2016-5-31
帖子
7
4
发表于 2016-7-17 08:33:31 | 只看该作者
taroxd 发表于 2016-7-17 07:08
如果每个人心里都能理解这些东西的话,感觉世界会清净很多(x

实例对象的英语到底是 instance 还是 obj ...

实例变量是instance,对象是object
回复 支持 反对

使用道具 举报

Lv1.梦旅人

梦石
0
星屑
50
在线时间
119 小时
注册时间
2016-2-27
帖子
353
5
发表于 2016-7-17 10:13:49 | 只看该作者
啊多谢大大的教程!

在下对于『类』还是不太掌握,有了大大的教程就比较容易理解了。
虽然在下还在学习编程语言……


最后那个的输出是不是
  1. "foo"
  2. "foo"
  3. true
复制代码

?

点评

是  发表于 2016-7-17 13:48
抓住喵喵然后扔给静兰  发表于 2016-7-17 11:17
啧, 不小心看漏一行aa = a【说错了【逃  发表于 2016-7-17 10:31
然而第三个是false ;-)  发表于 2016-7-17 10:31



在下的邮箱:[email protected] 联系请发信~
回复 支持 反对

使用道具 举报

Lv4.逐梦者 (版主)

梦石
0
星屑
9532
在线时间
5073 小时
注册时间
2013-6-21
帖子
3580

开拓者贵宾剧作品鉴家

6
发表于 2016-7-17 10:14:51 | 只看该作者
本帖最后由 RyanBern 于 2016-7-17 18:11 编辑

喵呜头像换得真勤快

这种东西不适合发水区了,养肥了之后应该送交技术发布区(

感觉喵呜需要再三强调:(某次)结果符合预期的代码 != 正确的代码,这点许多 Scripters 并不能理解。

还需要强调的是:千万不要拿别的语言来类比 Ruby。

点评

这种东西在前言里强调一下就得了……正文里插不进去啊  发表于 2016-7-17 13:47
回复 支持 1 反对 0

使用道具 举报

Lv1.梦旅人

梦石
0
星屑
76
在线时间
1379 小时
注册时间
2012-7-5
帖子
1698

开拓者

7
发表于 2016-7-17 10:39:47 | 只看该作者
诈尸

TL; NR
不是很懂你们代码触

感觉人人心里都理解了面向对象的话, 或许找对象也不会因此变得容易呢【x

点评

花式晒票  发表于 2016-7-17 17:41
花式晒票  发表于 2016-7-17 13:46

  -fk: -azogi:
回复 支持 反对

使用道具 举报

Lv4.逐梦者 (版主)

百合控

梦石
0
星屑
6643
在线时间
1275 小时
注册时间
2013-8-21
帖子
3657

开拓者

8
发表于 2016-7-17 11:05:44 | 只看该作者

噢噢噢噢 捕获喵污!


TL; NR
为何标签是胡扯

点评

那用什么标签?  发表于 2016-7-17 13:46
萌新瑟瑟发抖
看到我请叫我去干活
回复 支持 反对

使用道具 举报

Lv1.梦旅人

路人党员

梦石
0
星屑
52
在线时间
2276 小时
注册时间
2010-12-30
帖子
3225
9
发表于 2016-7-17 11:36:32 | 只看该作者
本帖最后由 英顺的马甲 于 2016-7-17 11:38 编辑

那我也来
  1. class A
  2.   def m1
  3.     p 'foo'
  4.   end
  5.   def p(s)
  6.     printf("not %s\n", s)
  7.   end
  8. end

  9. a = A.new
  10. aa = a.dup
  11. a.m1
  12. aa.m1
  13. p (a = aa)
复制代码

点评

对!这就是陷阱 XD  发表于 2016-8-1 12:07
等等是一个等号?  发表于 2016-7-31 22:46
是false?  发表于 2016-7-31 22:46
比如小白完全不知道.dup是什么自带的方法……  发表于 2016-7-17 20:15
不对,我这代码涉及了还几个槽(陷)点(阱)  发表于 2016-7-17 13:58
本人擅长XP,如果有脚本或者Ruby方面的问题欢迎发电邮到[email protected]咨询,本人很少检查电邮所以不一定会及时回复,本人不会直接出手解决问题只会提供一个方向,所以谢绝伸手党
回复 支持 反对

使用道具 举报

Lv4.逐梦者

梦石
2
星屑
5550
在线时间
2566 小时
注册时间
2012-2-9
帖子
990

开拓者

10
发表于 2016-7-17 13:37:50 | 只看该作者
本帖最后由 garfeng 于 2016-7-17 13:46 编辑

请教一下:
1.
  1. a = A.New
  2. b = A.New
复制代码

这是创建两个类相同的对象对吧,接下来的:
  1. p a == b
复制代码

在作比较的时候,这个==运算符比较的到底是什么呢?
我知道在某些语言里,==在比较对象时,时逐个比较成员变量和成员函数,全部相同则返回true,否则false。
ruby在比较时,比较的时什么呢?
【突然觉得,比较的是a和b指向的地址是否一样吗?,因为a和b都(大概)是指针(长整型),存放用于存放对象而开辟的内存起始地址(是个很长的整数)。】
从输出结果看,的确是比较两个指针里存放的地址的具体数值。
那么ruby里有没有类似于*p这种获取指向内容的运算符呢?

如果有的话,那么:


  1. (*a) == (*b)
复制代码

是不是应该输出true呢?

2.
  1. a = A.new
  2. b = a
复制代码

这里的b被赋值的是a的地址,还是另申请一个类A的内存,把a copy一个副本存放进去,再把b指向它呢?

当然从输出结果看,是前者。

点评

== 方法是可以自由定义的。  发表于 2016-7-17 14:11
所以,对于普通对象,你可以使用 clone 来拷贝一个内容相同地址不同的新对象,但是,你不能执行 1.clone ,这也是基于上面那个前提:整数地址不变  发表于 2016-7-17 13:55
谢谢~学习了  发表于 2016-7-17 13:55
是的,不过像整数这样的对象和其他对象不同,整数的地址是永远不变的,对整数的操作可以看成操作地址本身而不是操作对象本身  发表于 2016-7-17 13:54
包括整数之类的赋值,也是传递地址吗?比如a=1,b=a,这样b和a是指向同一个地址吗?  发表于 2016-7-17 13:50
回复 支持 反对

使用道具 举报

您需要登录后才可以回帖 登录 | 注册会员

本版积分规则

拿上你的纸笔,建造一个属于你的梦想世界,加入吧。
 注册会员
找回密码

站长信箱:[email protected]|手机版|小黑屋|无图版|Project1游戏制作

GMT+8, 2024-11-18 23:44

Powered by Discuz! X3.1

© 2001-2013 Comsenz Inc.

快速回复 返回顶部 返回列表