美文网首页
Ruby里面extend include prepend 区别

Ruby里面extend include prepend 区别

作者: SSS_ruby | 来源:发表于2019-11-01 11:15 被阅读0次

    在Ruby中,我们如果需要调用module的话可以使用extendincludeprepend,但是这些关键字具体有哪些区别呢。

    先创建一个Person类,并且定义一个FooModule模块

    class Person
      def introduce
        puts "hello, i am from Person"
      end
    end
    
    person = Person.new
    person.introduce
    #=> hello, i am from Person
    
    module FooModule
      def introduce
        puts "hello, i am from Person FooModule"
      end
    
      def current_time
        puts "current time is #{Time.now.to_s}"
      end
    end
    

    extend

    现在我们在Person类中使用extend关键字来调用模块,使用相关方法,并且打印出相关信息。

    class Person
      extend FooModule
    end
    
    Person.introduce
    # => hello, i am from FooModule
    person.introduce
    # => hello, i am from Person
    Person.current_time
    # => current time is 2019-11-01 10:53:04 +0800
    person.current_time
    # =>  undefined method `current_time' for #<Person:0x000000028395d0> (NoMethodError)
    

    我们由Person.introducePerson.current_time可以观察出来extend关键字的作用是为Person添加了2个类方法。

    include

    class Person
      include FooModule
    end
    
    Person.introduce
    # =>  undefined method `introduce' for Person:Class (NoMethodError)
    person.introduce
    # => hello, i am from Person
    Person.current_time
    # =>  undefined method `current_time' for Person:Class (NoMethodError)
    person.current_time
    # => current time is 2019-11-01 10:59:28 +0800
    

    上面两个类调用的方法都报错了可以看出,includeextend相反,include是为类中添加的实例方法,而不是类方法。

    prepend

    prependinclude同样都是为类中添加实例方法,但不同之处在于,引入模块后的方法链会有一点区别

    我们先看看 include的方法链

    class Person
      # extend FooModule
      include FooModule
      # prepend FooModule
    end
    
    puts Person.ancestors
    
    # =>Person
    # =>FooModule
    # =>Object
    # =>JSON::Ext::Generator::GeneratorMethods::Object
    # =>PP::ObjectMixin
    # =>Kernel
    # =>BasicObject
    

    再看看prepend

    
    class Person
      # extend FooModule
      # include FooModule
      prepend FooModule
    end
    
    puts Person.ancestors
    
    # =>FooModule
    # =>Person
    # =>Object
    # =>JSON::Ext::Generator::GeneratorMethods::Object
    # =>PP::ObjectMixin
    # =>Kernel
    # =>BasicObject
    

    可以看出FooModulePerson的顺序有什么不同,那么具体不同体现在哪,接下来我们调用方法就可以看出区别了。

    include

    class Person
      # extend FooModule
      include FooModule
      # prepend FooModule
    end
    person.introduce
    # => hello, i am from Person
    

    prepend

    class Person
      # extend FooModule
      # include FooModule
      prepend FooModule
    end
    person.introduce
    # => hello, i am from FooModule
    

    可以看到,如果使用prepend的话我们会优先去查找FooModule中的introduce方法(如果FooModule没有introduce方法话,会依次去祖先链的上一级去查找introduce方法),而include是优先在Person中去查找。

    相关文章

      网友评论

          本文标题:Ruby里面extend include prepend 区别

          本文链接:https://www.haomeiwen.com/subject/xghfbctx.html