• 浅说ruby嵌套函数



    想到这个问题是因为看了网上的一个问题,大家可以先看看:http://pivotallabs.com/users/nick/blog/articles/302-ruby-quiz-a-trick-question
     

    我先从第二个问题开始讲起:
     
    下面的演示可以在irb中,也可以自己写一个main.rb之类的文件运行尝试(我的ruby是1.9.3)
     
    首先,开始看一个最简单的函数,
     

    def foo  
        1  
    end  



    我们知道ruby的顶级作用域是一个名叫main的Object,那么foo是在self为main中定义的,那它是存在于哪里的呢?增加两行代码

    puts private_methods.include?(:foo)  #=> true
    puts Object.private_methods.include?(:foo)  #=> true
     

    说明foo这个函数成为了Object类中的一个private方法。怎么回事呢?
     
    这是因为ruby有一个当前类的概念,这里的当前类就是main的类型,即Object,所以,定义foo的时候,就是在Object中定义了一个private方法(附加问题:为什么是private?
     

    那回到那个日本人问的问题:
     

    def foo  
        def foo  
            1  
        end  
    end  


    运行下面的代码:

    puts private_methods.include?(:foo)  #=> true
    puts Object.private_methods.include?(:foo)  #=> true
    puts public_methods.include?(:foo)  #=> false
    puts Object.public_methods.include?(:foo)  #=> false
    puts foo  #=> nil
    puts private_methods.include?(:foo)  #=> false
    puts Object.private_methods.include?(:foo)  #=> false
    puts public_methods.include?(:foo)  #=> true
    puts Object.public_methods.include?(:foo)  #=> true
    puts foo #=> 1 

    这个时候应该注意到两个事情,第一个需要注意的是,当第一次调用foo的时候,返回值为nil,当第二次调用nil的时候,返回值为1。第二点需要注意的是,当第一次调用之前是foo属于Object的priavte方法,而当第一次调用结束以后,foo变成了Object的public方法。
     
    首先解释第一个问题,当第一次运行foo的时候,foo的功能是定义一个返回值为1的foo方法,而这个新方法将会覆盖原来的方法,所以,第二次调用的时候返回值就是1了。
     
    对于第二个问题的解释,不妨再看一个demo:
     

    class C  
        def main  
            private_hello  
        end  
    private  
        def private_hello  
            def public_hello  
                1  
            end  
        end  
    end  
      
    c =  C.new  
    puts c.private_methods.include?(:private_hello)  #=> true
    puts c.public_methods.include?(:public_hello)  #=> false
    c.main  
    puts c.public_methods.include?(:public_hello)  #=> true

     
    从结果可以分析得到,虽然是在private的方法中定义了一个新的方法,但是新的方法与它在哪儿被定义的是没有关系的,这也就解释了为什么在原来private的foo方法中定义了一个新的foo方法,而新方法是public的原因了。
     

    好,然后我们来看第二个问题。

    def foo  
        def bar  
            1  
        end  
    end  
      
    puts foo.bar  #=> 1


     
    小日本的问题:Is this some magical lightweight object creation syntax so you can do cool method chaining?
     
    我只能说,呵呵,这其实不是什么神奇的语法,foo.bar的意思是向self.foo的返回值发送一个名为bar的方法
     
    第一次调用foo在定义了bar的同时返回值是NilClass,也就说其实是没有返回值的然后是向nil发送了bar,这是什么意思呢?为什么可以行的通呢?想想前面的那个问题,不难理解,Object中存在了一个public方法,叫做bar再然后,nil是NilClass的一个对象,而NilClass是继承于Object,所以,如果向nil发送bar的时候,其实是会调用到Object的bar方法的

    def foo  
        def bar  
            1  
        end  
    end  
      
    foo  
    puts nil.methods.include?(:bar)  #=> true
    puts NilClass.ancestors  #=> [NilClass, Object, Kernel, BaseObject]


    应该说清楚了吧,好开心

  • 相关阅读:
    使用 HTTP 缓存机制提升系统性能
    白鹭分析
    HTML5屏幕适配标签设置
    深入了解使用egret.WebSocket
    VS2013配合EgretVS开发简单塔防游戏
    C++高级语言程序设计实验五-中国矿业大学
    C++高级语言程序设计实验四-中国矿业大学
    C++高级语言程序设计实验三-中国矿业大学
    C++高级语言程序设计实验二-中国矿业大学
    C++高级语言程序设计实验一-中国矿业大学
  • 原文地址:https://www.cnblogs.com/java20130722/p/3206863.html
Copyright © 2020-2023  润新知