扫描二维码关注官方公众号
返回列表
+ 发新帖
查看: 107|回复: 0

[转载发布] 【初阶】构建更智能的方法 - Ruby方法相关

[复制链接]
累计送礼:
0 个
累计收礼:
0 个
  • TA的每日心情
    开心
    昨天 18:01
  • 签到天数: 114 天

    连续签到: 4 天

    [LV.6]常住居民II

    2338

    主题

    403

    回帖

    1万

    积分

    管理员

    Rank: 9Rank: 9Rank: 9

    VIP
    6
    卡币
    10627
    OK点
    16
    推广点
    0
    同能卷
    0
    积分
    13396

    灌水之王

    发表于 2024-4-19 17:46:05 | 显示全部楼层 |阅读模式
    这个东西估计你看了也没用,很少人的工程中能用上这些东西。不过你必须承认,有了这些东西,可以使方法更具有弹性,更加灵活。

    另外,欢迎大家丢砖指正。测试环境是Ruby1.8.1(RGSS),RGSS2也完全可以,甚至于Ruby1.9.6也能成功运行本次范例。

    一、迭代
    迭代允许我们执行由我们传递的一个语句块,当然,使用关键字yield。
    1. def a_yield_method    yieldend复制代码
    复制代码
    调用a_yield_method {p "hi! I am a yield-method."},由花括号扩住的正是我们所谓的“语句块”。事实上,你可以把一对{}替换为do~end,这似乎只关乎美观和“结合能力”的问题。
    1. a_yield_method {p "hi! I am a yield-method."}#=> "hi! I am a yield-method."复制代码
    复制代码
    这样做有个严重的问题,当我们没有传递块的时候,会触发LocalJumpError。Kernel模块提供了一个完美的解决办法,block_given?返回true或flase来标识是否传递了一个块。于是我对上一个方法稍作修改:
    1. def a_yield_method  if block_given?    yield                        # 如果传递了块就迭代  else    p "Miss"                        # 没传递就显示丢失  endend复制代码
    复制代码
    这样就可以确保万无一失,同时yield关键字可以让我们对原方法随时扩容,这是否又是得益于Ruby的强动态性呢?

    二、块参数


    在参数前加一个&,让他变成块参数,使得他可以接受Proc对象。值得一提的是,这里的&可不是C语言里面的取址运算符。
    1. def a_proc_method( &proc )  p proc.class  yield if block_given?  proc.call if block_given?enda_proc_method#=> NilClassa_proc_method { p "Double Kill" }#=> Proc#=> "Double Kill"#=> "Double Kill"复制代码
    复制代码
    这个例子很容易理解,我们利用反射机制检测着proc参数,并且如果传递了块就迭代并调用proc的call方法(由Proc类提供)。

    三、参数列表

    参数前加(一元)星号,是他称为参数列表(可变参数)。可变参数是一个数组对象,应该在定义方法时置于最后,并且没有默认值。可以用for关键字或者each(Array类提供)等方法遍历参数。

    展望:Ruby 2.0以上的版本中,将添加**二元星号(作用貌似是可变参数,但是一个Hash对象?)。
    1. def multiple_arg_method( *args )  args.each do |e|    p e  endendmultiple_arg_method(1,"2",3.0,[4,5],{6=>7},Proc.new{p "hi"})#=> 1#=> "2"#=> 3.0#=> [4,5]#=> {6=>7}#=> #复制代码
    复制代码
    方法内部,我采取的策略是使用each方法迭代每一个元素,并用p给输出出来。可以想象,我们利用可变参数做一个简单的加法方法:
    1. def sum( *args )  result = 0  args.each do |e|    result += e  end  return resultendp sum(1,2,3,4,5,6,7,8,9)#=> 45复制代码
    复制代码
    四、活用反射机制

    众所周知,向量可以于一个数量相乘,亦可以于一个向量相乘,因此,我们可以利用反射机制定义一个智能的方法,辨识传递的参数,并作出智能的部署:

    在本例中,假设向量是由Vector类管理,数量是由Numeric类管理。我们在Vector类里重载*运算符,向量的x,y坐标以@x,@y这两个实变量的形式存储。
    1. def *( opt )  if opt.is_a? Numeric                # 是数量    self.x *= opt    self.y *= opt    return self  elsif opt.is_a? Verctor        # 是向量    return self.x * opt.x + self.y * opt.y  endend复制代码
    复制代码
    很明显,我们利用is_a?方法,判定传递过来的参数是那个类的实例,从而决定改如何操作,这的确让方法变得灵活。当然也可以用.kind_of?或者.class.ancestors.include?方法来确定。

    五、参数默认值

    我们可以给参数制定默认值,当没有传递参数时,这使得Ruby不会发生ArgumentError。
    1. class Human  attr_reader :age  def initialize( age = 0)    @age = age  end endguest = Human.newp guest.age #=> 0复制代码
    复制代码
    没有传递参数,也可以正常使用?真是莫大的方便




    为什么有此文?晚上睡不着觉起来蛋疼……
                 本帖来自P1论坛作者DeathKing,因Project1站服务器在国外有时候访问缓慢不方便作者交流学习,经联系P1站长fux2同意署名转载一起分享游戏制作经验,共同为国内独立游戏作者共同创造良好交流环境,原文地址:https://rpg.blue/forum.php?mod=viewthread&tid=142147  若有侵权,发帖作者可联系底部站长QQ在线咨询功能删除,谢谢。
    天天去同能,天天有童年!
    回复 送礼论坛版权

    使用道具 举报

    文明发言,和谐互动
    文明发言,和谐互动
    高级模式
    您需要登录后才可以回帖 登录 | 立即注册

    本版积分规则

    关闭

    幸运抽奖

    社区每日抽奖来袭,快来试试你是欧皇还是非酋~

    立即查看

    聊天机器人
    Loading...

    QQ|Archiver|手机版|小黑屋|同能RPG制作大师 ( 沪ICP备12027754号-3 )

    GMT+8, 2025-3-15 00:44 , Processed in 0.113430 second(s), 53 queries .

    Powered by Discuz! X3.4

    Copyright © 2001-2020, Tencent Cloud.

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