楼主: 喵呜喵5

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

[复制链接]

路人党员

梦石
0
星屑
52
在线时间
2276 小时
注册时间
2010-12-30
回帖
3011
发表于 2016-7-17 14:07:56 | 显示全部楼层
本帖最后由 英顺的马甲 于 2016-7-17 14:34 编辑

再来一段,这一段当初朋友都疑惑了好久
  1. def xor(a, b)
  2.   return ((a ? true : false)!=(b ? true : false)) # 这里刚刚不小心写成了 ==
  3. end
  4. ary1 = [1,2,3,4,5]
  5. ary2 = [2,4,6,8,10]
  6. p xor(ary1.include?(1), ary1.include?(2))
  7. p xor(ary2.include?(1), ary2.include?(2))
  8. p xor(ary1.include?(0), ary2.include?(1))
  9. p xor(ary1, ary2)
  10. p xor(nil, ary2)
复制代码

点评

! 运算符可以被重定义。不然直接写 (!a) ^ (!b) 就好了  发表于 2016-7-17 17:17
是可以,不过a?true:false的效率比较高  发表于 2016-7-17 16:44
其实我猜(a ? true : false)可以写成!!a  发表于 2016-7-17 16:29
对,但是这是我能想到的最简单的实现xor的方法,当初在想怎么弄SQL的xor时想到的,不过貌似写错了  发表于 2016-7-17 14:34
感觉就是一个 Ruby 里除了 nil 和 false 是假以外其他都是真?  发表于 2016-7-17 14:29
本人擅长XP,如果有脚本或者Ruby方面的问题欢迎发电邮到engshun@1ppl.me咨询,本人很少检查电邮所以不一定会及时回复,本人不会直接出手解决问题只会提供一个方向,所以谢绝伸手党
回复

使用道具 举报

梦石
0
星屑
1944
在线时间
404 小时
注册时间
2015-8-30
回帖
322
发表于 2016-7-17 14:10:03 | 显示全部楼层
至今没搞懂为啥同一个类的实例在执行了同一个方法之后会变成不同的东西。

点评

因为你的代码不是用面向对象的思考方式去写的啊  发表于 2016-7-17 15:38
但为什么不是我期待的。。?  发表于 2016-7-17 15:35
因为实例和实例之间是不同的东西正是我们所期待的啊  发表于 2016-7-17 14:39
这个论据同样不正确。因为虽然“人”和“复制人”相同,但是“复制人”执行了“死”之后不会使“人”也执行“死”。  发表于 2016-7-17 14:20
你是人类,你可以被复制,于是有了你的复制人,然后你的复制人被杀了,请问你死了吗?  发表于 2016-7-17 14:18
小仙女一枚~
回复

使用道具 举报

路人党员

梦石
0
星屑
52
在线时间
2276 小时
注册时间
2010-12-30
回帖
3011
发表于 2016-7-17 14:31:29 | 显示全部楼层
本帖最后由 英顺的马甲 于 2016-7-17 14:35 编辑
有丘直方 发表于 2016-7-17 14:10
至今没搞懂为啥同一个类的实例在执行了同一个方法之后会变成不同的东西。 ...

  1. class Human
  2.   attr_reader :DNA
  3.   attr_reader :characteristic
  4.   def initialize
  5.     @DNA = rand
  6.     @characteristic = rand
  7.     [url=home.php?mod=space&uid=89503]@deAd[/url] = false
  8.   end
  9.   def same_as?(other)
  10.     return (other.is_a?(Human) and @DNA == other.DNA and @characteristic == other.characteristic)
  11.   end
  12.   def kill
  13.     print "dead"
  14.     @dead = true
  15.   end
  16.   def dead?
  17.     return @dead
  18.   end
  19. end
  20. 有丘直方 = Human.new
  21. p 有丘直方.is_a?(Human)
  22. temp = 有丘直方
  23. p temp == 有丘直方
  24. 复制人 = 有丘直方.clone
  25. p 复制人.is_a?(Human)
  26. 复制人.same_as?(有丘直方)
  27. p 复制人 == 有丘直方
  28. 复制人.kill
  29. p 复制人.dead?, 有丘直方.dead?
  30. p 复制人.same_as?(有丘直方)
  31. 有丘直方.kill
  32. p 有丘直方.dead?
  33. p 复制人.same_as?(有丘直方)
复制代码

点评

我不需要你写一个示例代码,因为我知道你的论点正确,我只想知道为什么你的论点正确。  发表于 2016-7-17 15:50
我擦,这@人的bug又出现了  发表于 2016-7-17 14:48

评分

参与人数 1星屑 +5 收起 理由
有丘直方 + 5

查看全部评分

本人擅长XP,如果有脚本或者Ruby方面的问题欢迎发电邮到engshun@1ppl.me咨询,本人很少检查电邮所以不一定会及时回复,本人不会直接出手解决问题只会提供一个方向,所以谢绝伸手党
回复

使用道具 举报

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

开拓者

发表于 2016-7-17 15:10:48 | 显示全部楼层
看英叔这么开心突然也想来一个好玩的【
  1. def a
  2.   def a
  3.     2
  4.   end
  5.   1
  6. end
  7. p [a, a]
复制代码

点评

最外层的a被调用后会定义一个新的a  发表于 2016-7-17 15:24
啧,原来这个def 是全局的……  发表于 2016-7-17 15:15
[1,1]?我猜(  发表于 2016-7-17 15:14

  -fk: -azogi:
回复

使用道具 举报

梦石
0
星屑
1944
在线时间
404 小时
注册时间
2015-8-30
回帖
322
发表于 2016-7-17 15:46:59 | 显示全部楼层
  1. class Human
  2.   attr_reader :DNA
  3.   attr_reader :characteristic
  4.   def initialize
  5.     @DNA = rand
  6.     @characteristic = rand
  7.     [url=home.php?mod=space&uid=89503]@deAd[/url] = false
  8.   end
  9.   def same_as?(other)
  10.     return (other.is_a?(Human) and @DNA == other.DNA and @characteristic == other.characteristic)
  11.   end
  12.   def kill
  13.     print "#{self}died!\n"
  14.     @dead = true
  15.   end
  16.   def dead?
  17.     return @dead
  18.   end
  19. end
  20. 有丘直方 = Human.new
  21. p 有丘直方.is_a?(Human)
  22. temp = 有丘直方
  23. p temp == 有丘直方
  24. 复制人 = 有丘直方.clone
  25. p 复制人.is_a?(Human)
  26. 复制人.same_as?(有丘直方)
  27. p 复制人 == 有丘直方
  28. 复制人.kill
  29. p 复制人.dead?, 有丘直方.dead?
  30. p 复制人.same_as?(有丘直方)
  31. 有丘直方.kill
  32. p 有丘直方.dead?
  33. p 复制人.same_as?(有丘直方)
复制代码
在ruby的运行结果是
  1. true
  2. true
  3. true
  4. false
  5. #<Human:0x872fd0>died!
  6. true
  7. nil
  8. true
  9. #<Human:0x873048>died!
  10. true
  11. true
复制代码
我知道你的论点是正确的,但是我想要知道为什么会这样。因为本身我没有指出你的论点错误,我也不想辩论,所以我只是想知道原因而已,你就需要告诉我一个答案。
小仙女一枚~
回复

使用道具 举报

梦石
0
星屑
1944
在线时间
404 小时
注册时间
2015-8-30
回帖
322
发表于 2016-7-17 15:47:28 | 显示全部楼层
  1. class Human
  2.   attr_reader :DNA
  3.   attr_reader :characteristic
  4.   def initialize
  5.     @DNA = rand
  6.     @characteristic = rand
  7.     [url=home.php?mod=space&uid=89503]@deAd[/url] = false
  8.   end
  9.   def same_as?(other)
  10.     return (other.is_a?(Human) and @DNA == other.DNA and @characteristic == other.characteristic)
  11.   end
  12.   def kill
  13.     print "#{self}died!\n"
  14.     @dead = true
  15.   end
  16.   def dead?
  17.     return @dead
  18.   end
  19. end
  20. 有丘直方 = Human.new
  21. p 有丘直方.is_a?(Human)
  22. temp = 有丘直方
  23. p temp == 有丘直方
  24. 复制人 = 有丘直方.clone
  25. p 复制人.is_a?(Human)
  26. 复制人.same_as?(有丘直方)
  27. p 复制人 == 有丘直方
  28. 复制人.kill
  29. p 复制人.dead?, 有丘直方.dead?
  30. p 复制人.same_as?(有丘直方)
  31. 有丘直方.kill
  32. p 有丘直方.dead?
  33. p 复制人.same_as?(有丘直方)
复制代码
在ruby的运行结果是
  1. true
  2. true
  3. true
  4. false
  5. #<Human:0x872fd0>died!
  6. true
  7. nil
  8. true
  9. #<Human:0x873048>died!
  10. true
  11. true
复制代码
我知道你的论点是正确的,但是我想要知道为什么会这样。因为本身我没有指出你的论点错误,我也不想辩论,所以我只是想知道原因而已,你就需要告诉我一个答案。

点评

因为clone这个函数会把实例除了object_id以外的其他数据一模一样地复制到另一个实例并且返回复制出来的实例啊,clone就是复制的意思  发表于 2016-7-17 15:54
小仙女一枚~
回复

使用道具 举报

路人党员

梦石
0
星屑
52
在线时间
2276 小时
注册时间
2010-12-30
回帖
3011
发表于 2016-7-17 16:05:17 | 显示全部楼层
关于实例的问题以前倒是有这么个脑残贴
链接:残脑帖,来说说rmxp储存后的阿尔西斯还是原来的阿尔西斯吗
  1. class A
  2. end
  3. a = A.new
  4. p a.object_id
  5. b = a
  6. p b.object_id
  7. p b == a
  8. b = Marshal.load(Marshal.dump(b))
  9. p b.object_id
  10. p b == a
  11. b = ObjectSpace._id2ref(a.object_id)
  12. p b.object_id
  13. p b == a
复制代码
本人擅长XP,如果有脚本或者Ruby方面的问题欢迎发电邮到engshun@1ppl.me咨询,本人很少检查电邮所以不一定会及时回复,本人不会直接出手解决问题只会提供一个方向,所以谢绝伸手党
回复

使用道具 举报

梦石
0
星屑
2826
在线时间
2634 小时
注册时间
2013-1-16
回帖
5453

贵宾

发表于 2016-7-17 16:49:56 | 显示全部楼层
满脑子面向过程的弱鸡瑟瑟发抖
(Created by @喵kano)


施工现场:hotege.github.io
回复

使用道具 举报

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

开拓者

发表于 2016-7-17 17:10:19 | 显示全部楼层
本帖最后由 garfeng 于 2016-7-18 15:16 编辑
有丘直方 发表于 2016-7-17 14:10
至今没搞懂为啥同一个类的实例在执行了同一个方法之后会变成不同的东西。 ...

我猜你想问10楼我问过的东西。
因为开辟了不一样的内存地址来存储实例,而在比较时,默认==符号比较的是地址的值,而非实例里的成员的具体值。
内存地址不一样了,所以会不是同一个东西。

个人理解所写,欢迎拍砖:

[pre lang="ruby"] a = A.new
b = a
             Addr  Data    这是一个内存条
             +---+-------+
a ---------> | 1 |   3   |-------+
             +---+-------+       |
b ---------> | 2 |   3   |----+  |
             +---+-------+    |  |
             | 3 |       |<---+--+
             +---| Obj1  |
             | 4 |       |
             +---+-------+
             |...| ..... |
             +---+-------+

a = A.new
申请3~4的内存,吧Obj1存进去,将a赋值3
a --> Addr:1 --> Data:3 --> Addr:3 --> Obj1
b = a
b --> Addr:2 --> Data:3 --> Addr:3 --> Obj1

a和b都是3,所以
a==b # =>>true
a equal? b # =>> true
a eql? b   # =>> true

==========================================================================

a = A.new
b = A.new

               
              Addr  Data        这是一个内存条
              +---+-------+
a ----------> | 1 |   3   |----+  a存储的内容是3,即obj1的起始地址位
              +---+-------+    |  ---------------------------------------
b ----------> | 2 |   5   |----+--+ b存储的内容是5,即obj2的起始地址位
              +---+-------+    |  | -------------------------------------
              | 3 |       |<---+  |
              +---+  Obj1 |       | 3,4号地址位里存储的内容obj1,和
              | 4 |       |       | 5,6号里存储的obj2一模一样。
              +---+-------+       | 假设hash也一样?
              | 5 |       |<------+
              +---+  Obj2 |
              | 6 |       |
              +---+-------+
                           
                           
当使用a所代表的object时,访问顺序:

a --> Addr:1 --> Data:3 --> Addr:3 --> Data:Obj1
b --> Addr:2 --> Data:5 --> Addr:5 --> Data:Obj2

a是3,而b是5,所以
a==b #=>>false
a equal? b # =>> false
a eql? b # =>> true

=====================================================================
                           
涉及到哈希值的比较?

a = A.new
b = a.dup
             +---+--------+
a ---------> | 1 |   3    |----+
             +---+--------+    |
b ---------> | 2 |   5    |----+---+
             +---+--------+    |   |
             | 3 | Obj1   |<---+   |
             +---+ hash1  |        | hash1 和hash2 不一样,
             | 4 |        |        | 除此之外,Obj1和Obj2的
             +---+--------+        | 其他内容都一样?
             | 5 | Obj2   |<-------+
             +---+ hash2  |
             | 6 |        |
             +---+--------+

a==b #=>>false
a equal? b =>> false
a eql? b =>> false
[/pre]


慎点……朋友学过c吗?
比如:
  1. #include <stdio.h>
  2. #include <stdlib.h>
  3. #include <string.h>

  4. int main() {
  5.         char *a;
  6.         char *b;
  7.         char c[20] = "hello world";

  8.         a = c;
  9.         b = c;

  10.         //这时a,b都指向同一个地址,c
  11.         printf("a==?b : %d\n", a == b); //1,也就是true
  12.         //可以打印出地址的具体值
  13.         printf("addr a = %p ;addr b = %p\n", a, b);



  14.         //这时,a,b都指向分别申请的不同地址的开头,但它们存储的内容一模一样
  15.         a = (char *)malloc(sizeof(char) * 20);
  16.         memcpy(a, c, sizeof(char) * 20);

  17.         b = (char *)malloc(sizeof(char) * 20);
  18.         memcpy(b, c, sizeof(char) * 20);

  19.         printf("a==?b : %d\n", a == b); //0,也就是false,比较的是地址
  20.         //可以打印出地址的具体值
  21.         printf("addr a = %p ; addr b = %p\n", a, b);

  22.         printf("*a==?*b : %d\n", (*a) == (*b)); //1,也就是true,比较的是a,b指向的地址所存储的值,该值是一个char,即“h”。
  23.         //可以打印出地址里存储的内容
  24.         //以int打印
  25.         printf("value(int) of a = %d ; value(int) of b = %d\n", *a, *b);
  26.         //以ascii字符打印
  27.         printf("value(char) of a = %c ; value(char) of b = %c\n", *a, *b);

  28. }



复制代码


输出:

$ ./test.exe
a==?b : 1
addr a = 000000000024FE20 ;addr b = 000000000024FE20
a==?b : 0
addr a = 0000000000571220 ; addr b = 0000000000571240
*a==?*b : 1
value(int) of a = 104 ; value(int) of b = 104
value(char) of a = h ; value(char) of b = h







上面这段不是对象,但能从根本解释为何两个对象的实例不能划等号。
面向对象是从面向过程抽象出来的。
把类视为结构体,
把类的成员变量视为结构体的成员值(值或者指针),该值指向一段存储具体数值的内存地址,
把类的成员函数视为结构体成员值(指针类型),指向存储某函数的内存地址。
把类的self/this关键字视为一个指针,指向本实例的地址。



【再继续下去就需要写内存存放数据的方式了……】


263646951524954445.jpg

买一本《深入理解计算机系统》吧。


点评

多写写就好了……然后,因为涉及到地址和内存,有很多问题,写了30年以上的人也还会犯,有本书,c语言的陷阱和漏洞,看了后会很舒畅。  发表于 2016-7-17 22:12
学C++的路过,表示到了对象和指针的讲解就完全迷糊了……  发表于 2016-7-17 20:19
是的!~~  发表于 2016-7-17 19:31
童鞋说的是我画的娃娃吗?是mv的  发表于 2016-7-17 19:09
MV吧!?感觉就是VA番薯头身的肥大版。  发表于 2016-7-17 18:35

评分

参与人数 1星屑 +5 收起 理由
有丘直方 + 5

查看全部评分

回复

使用道具 举报

梦石
0
星屑
9557
在线时间
5074 小时
注册时间
2013-6-21
回帖
3459

开拓者贵宾剧作品鉴家

发表于 2016-7-17 18:06:46 | 显示全部楼层
本帖最后由 RyanBern 于 2016-7-17 18:09 编辑
garfeng 发表于 2016-7-17 17:10
我猜你想问10楼我问过的东西。
因为开辟了不一样的内存地址来存储实例,而在比较时,默认==符号比较的是地 ...


永远不要用其他语言来类比Ruby,尤其是C语言。这也是我初学的时候犯的错误之一。

首先吐槽为什么输出指针不用%p而是%d

下面是从 Ruby 官方文档上截取下来的。
链接:http://ruby-doc.org/core-2.3.1/Object.html#method-i-eql-3F
firefox_2016-07-17_18-04-36.png
请自己体会一下 Ruby 的这个机制(约定)。顺便修改一下回复吧。

点评

啧 这跟截图软件有关  发表于 2016-7-18 09:55
我更想知道怎样截图才能把鼠标截进去  发表于 2016-7-17 22:54

评分

参与人数 1星屑 +100 收起 理由
garfeng + 100 谢谢~

查看全部评分

回复

使用道具 举报

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

本版积分规则

Powered by Discuz! X5.0 © 2001-2026 Discuz! Team.

在本版发帖返回顶部