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

Project1

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

[通用发布] Ruby 中往往会被忽略的地方 [ incomplete ]

[复制链接]

Lv2.观梦者

虚構歪曲

梦石
0
星屑
364
在线时间
1198 小时
注册时间
2010-12-18
帖子
3928

贵宾

跳转到指定楼层
1
发表于 2012-8-5 14:48:39 | 只看该作者 回帖奖励 |倒序浏览 |阅读模式

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

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

x
本帖最后由 忧雪の伤 于 2012-8-6 15:17 编辑



前言:以下内容没有一个是你在平常的游戏制作中需要的,所以纯粹是来看教学的可以绕道了。


① 元类 ( metaclass )

先看一段代码。
  1. class << foo = Object.new
  2.   def foo
  3.     p 0
  4.   end
  5. end
  6. foo.foo
复制代码
class << class 有什么区别呢?为什么可以在一个不是类的对象前使用呢?
其实这个行为相当于把一个匿名类混合插入(mix-in)进对象,这个行为就和 include 相似。  
所以对象就会拥有这些新的实例方法了。
以上的行为就像添加对象的特殊方法,并不会影响到原本的类和其他实例。
(实际上不少人都把它这样用了,例如有人说可以用这个方式来代替 Module#module_function
这个行为有个好处就是可以用类的方法,比如 Class#attr_accessorClass#alias_method什么的。你甚至可以往这里 include,不污染到原本的类什么的。
  1. class << foo = Object.new
  2.   def foo
  3.     p 0
  4.   end
  5.   alias_method :bar, :foo
  6. end
  7. foo.bar
复制代码
不过说到底这些根本很少会用到吧?
这个匿名类也是一个实际存在的对象,我们可以通过编写一个快捷的方法来获得它。
  1. class Object
  2.   def metaclass
  3.     class << self
  4.       self
  5.     end
  6.   end
  7. end
  8. p Object.new.metaclass
复制代码
就可以获取到了~至于这个对象有什么用就是你要研究的事情了。
元类是个很神奇的东西,笔者有很多事情到现在都无法理解。(不会告诉你笔者是才刚懂的)
元类也有一种叫法叫单例类(Singleton Class)。(从异常报告来看似乎 Ruby 自己的叫法就是这个)

② 过程对象 ( Proc )

RPG Maker 中,如果你需要一个变量或者常量随时返回一个 #Game_Variable 的值怎么办?
难道是 var = $game_variable[var_id] #Fixnum 是即时值,var 并不会随着 $game_variable[var_id] 的改变而改变。
于是你可以这样做。
  1. block = proc { $game_variable[var_id] }
复制代码
当然这时直接 p block 返回的是一个 #Proc,并不是我们想要的 #Fixnum,我们需要让它启动,因为这实际上处于一个封装的状态。
  1. var = block.call
  2. p var
复制代码
这样就能让它启动。是不是很神奇呢?
实际上这和方法的原理相同,都是封装的过程,在你调用的时候进行计算。
而且一样可以带参数(块的参数),例如。
  1. block = proc {|arg| p arg }
  2. p block.call 0
复制代码
这简直就像无名函数一样。
过程对象在构建的时候会导入当前作用域的局部变量,这需要注意。
  1. foo = 0
  2. proc { p foo }
复制代码
RPG Maker XP 的默认脚本中就用到了这个来传递实例变量(虽然我觉得根本没这个必要……)

Object#instance_eval

如果想在当前作用域中进入其他对象的作用域怎么办?
Ruby 为我们提供了非常便捷的方法,那就是 instance_eval
它可以干什么呢?
例如,为对象定义一个它的实例变量?
  1. Object.new.instance_eval { @foo = 0 }
复制代码
实际上,这个方法是在调用对象的作用域中计算所带的块。
可以做到一些很方便的事情哦,毕竟是跨了作用域。当然要怎么玩都由你们自己发现了。
此外它也支持像 eval 一样计算字符串的功能,例如。
  1. Object.new.instance_eval 'p self'
复制代码

④方法对象 ( Method )

如果需要在一个对象调用另外一个对象的方法怎么办(这两个对象本身作用域不同)?
Ruby 有一个特殊的类 Method,它不能通过 Class#new 生成实例,而是要通过 Object#method 来生成它的实例。
Object#method 可以把对象的方法变为方法对象,把方法和被调对象都封装在了一起,例如。
  1. class Foo
  2.   def foo
  3.   end
  4. end
  5. foo = Foo.new
  6. method = foo.method :foo
  7. p method
复制代码
如果执行这个对象,相当于调用了那个方法。
  1. class Foo
  2.   @@foo = []
  3.   def foo
  4.     @@foo << 0
  5.   end
  6. end
  7. method = Foo.new.method :foo
  8. method.call
  9. class Foo
  10.   p @@foo
  11. end
复制代码
所以才能做到跨作用域调用原对象的方法。
因为是封装,所以即使之后原来的方法被再定义也还是不会有变动。
  1. class Foo
  2.   @@foo = []
  3.   def foo
  4.     @@foo << 0
  5.   end
  6. end
  7. method = Foo.new.method :foo
  8. class Foo
  9.   def foo
  10.     @@foo.pop
  11.   end
  12. end
  13. method.call
  14. class Foo
  15.   p @@foo
  16. end
  17. Foo.new.foo
  18. class Foo
  19.   p @@foo
  20. end
复制代码
Ruby 还提供了一个非常有用的方法,那就是 Method#receiver,可以返回原来的被调对象。
  1. class Foo
  2.   def foo;  end
  3. end
  4. foo = Foo.new
  5. foo.equal? foo.method(:foo).receiver
复制代码


结言:大家看完了之后是不是感觉被坑了呢?反正笔者自己感觉是的。笔者暂时想到的就这么多,如果有其他新奇的东西也请麻烦提出来吧~ → 其实笔者自己也是个小白。


Lv1.梦旅人

Mr.Gandum

梦石
0
星屑
226
在线时间
2070 小时
注册时间
2007-1-31
帖子
3039

贵宾

2
发表于 2012-8-5 15:41:29 | 只看该作者
本帖最后由 feizhaodan 于 2012-8-5 15:41 编辑

我会说我之前玩instance_eval class_eval啥的把自己玩傻了么= =

  1. class << foo = Object.new
复制代码
这个的语法求解= =
回复 支持 反对

使用道具 举报

Lv2.观梦者

虚構歪曲

梦石
0
星屑
364
在线时间
1198 小时
注册时间
2010-12-18
帖子
3928

贵宾

3
 楼主| 发表于 2012-8-5 15:44:48 | 只看该作者
feizhaodan 发表于 2012-8-5 15:41
我会说我之前玩instance_eval class_eval啥的把自己玩傻了么= =

这个的语法求解= = ...

UI> 就是 foo = Object.new;  class << foo 而已啦……
      话说还真有人吐槽这个……囧,写的时候就猜到了。

点评

了解了= =b  发表于 2012-8-5 15:50
回复 支持 反对

使用道具 举报

Lv1.梦旅人

青山绿水长留生

梦石
0
星屑
50
在线时间
369 小时
注册时间
2010-12-17
帖子
442
4
发表于 2012-8-5 16:10:14 | 只看该作者
Continuation和ObjectSpace都是冷门的东西,但有时候很有意思
回复 支持 反对

使用道具 举报

Lv1.梦旅人

梦石
0
星屑
110
在线时间
953 小时
注册时间
2007-4-25
帖子
805
5
发表于 2012-8-6 03:55:04 | 只看该作者
这个匿名类也是一个实际存在的对象,我们可以通过编写一个快捷的方法来获得它。

1.9 以後可以用 Object#singleton_class。

元类也有一种叫法叫特殊类(Singleton Class)。

「Singleton Class」的翻譯是「單例類」,「特殊類」對應的是「Eigenclass」。

点评

UI> = = 我看一个人写的文章里面又把 Eigenclass 叫做单例类了……  发表于 2012-8-6 10:53
[email protected]:~> repeat 1 fortune
Matz is nice, so we are nice.
回复 支持 反对

使用道具 举报

Lv2.观梦者

虚構歪曲

梦石
0
星屑
364
在线时间
1198 小时
注册时间
2010-12-18
帖子
3928

贵宾

6
 楼主| 发表于 2012-8-6 10:49:38 | 只看该作者
本帖最后由 忧雪の伤 于 2012-8-6 11:04 编辑
苏小脉 发表于 2012-8-6 03:55
1.9 以後可以用 Object#singleton_class。

特殊类
Singleton Class
只对应于某特定对象的假想类。

都怪我参考的是脑残的中文手册么……

前面那个方法还真的第一次见呢。
回复 支持 反对

使用道具 举报

Lv3.寻梦者

梦石
0
星屑
1323
在线时间
831 小时
注册时间
2007-12-25
帖子
1558
7
发表于 2012-8-6 12:36:53 | 只看该作者
看不球懂,知道是好东西,果断收藏,几年后再来看!
精卫赤龙腾   
总是存在一种强大,去完成似乎不可能的事情.
无畏战乾程   
或是需要一种勇气,去挑战几乎不存在的胜利.
一味玄真魂     
这是拥有一种恒心,去化解根本没有解的困难.
烈卫开天径    
只是带着一种决心,去争取残存的最后的希望。
回复 支持 反对

使用道具 举报

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

本版积分规则

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

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

GMT+8, 2024-12-25 00:42

Powered by Discuz! X3.1

© 2001-2013 Comsenz Inc.

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