分享 [原创] Ruby 初学者水平自测代码

daqing · 2012年04月01日 · 最后由 cryjay2012 回复于 2017年02月09日 · 5445 次阅读

经常有初学者问,Ruby水平学到什么程度,可以去学习Rails了呢?我来分享一段代码,如果初学者能够看懂,说明水平可以了:

module Foo
  def self.included(base)
    base.class_eval do
      extend ClassMethods
      include InstanceMethods
    end
  end

  module ClassMethods
    def hello
      new.world
    end
  end

  module InstanceMethods
    def world
      puts "Hello, world"
    end
  end
 end

class Bar
  include Foo
  hello
end

# 程序最后会输出: Hello, world


----------------- 更好的写法如下 --------------------

module Foo
  def self.included(base)
    base.class_eval do
      extend ClassMethods
    end
  end

  module ClassMethods
    def hello
      new.world
    end
  end

  def world
    puts "Hello, world"
  end
 end

class Bar
  include Foo
  hello
end

# 程序最后会输出: Hello, world


共收到 43 条回复

继续去看书。。。。

基本没学过ruby,但是基本都明白了,就是new.world不理解

#2楼 @lucky215 new.world,就是创建一个对象,再调用这个对象的world方法。

#2楼 @lucky215 extend ClassMethods 把hello变成Bar的类方法 类方法的self默认是当前类,也就是Bar 调用hello还是类的作用域,self还是Bar

偶也在继续看书,刚学到数组模块。看到了几个模块和方法的定义,class_eval和extend还没学到。

能看懂。细节没看懂-_-#。还得学啊。

@daqing@cxh116 谢谢了,就是创建了bar对象,然后调用了world方法吧

#7楼 @lucky215 对。new().world就好看了。

我不懂的是

def self.included(base)
  base.class_eval do
    extend ClassMethods
    include InstanceMethods
  end
end

这块,估计看看书也能懂。

@jinleileiking 谢谢,这块倒也没细看,只是知道在干什么,但是具体就不懂了

#9楼 @lucky215 这块我感觉比那块难

self.included(base) 一个调用方法 base.class_eval 将随后的 块中的 方法和类 加入 Foo

include => includes code into class. extend => extends using module, appends class methods.

这里都是 把 两个函数 放到 Foo中

后面 是对 两个module的 定义

Bar 把Foo的 两个方法 包含了进来 并且 调用了 hello 不知道还对不对 楼下继续

有一个 疑问 就是 我查了 核心库中并没有 included 这个方法 是不是 self.method_name 会在 类初始化实例的时候 就会执行么 不然它是怎么 引用 两个 module的呢 没有看见 included 的调用

还不是很明白。坐等楼下。我懒啊。@hooopo解释一下吧

#13楼 @jinleileiking 去翻书吧 我更懒 差不多任意一本ruby入门书上都有。。。

#14楼 @hooopo 难道你不看书,不懂?-_-# 让我失望了啊

我要去看书了,谢谢。

#15楼 @jinleileiking :) @hooopo 的意思是示例代码展示的都是Ruby的基本知识。双飞燕 和 镐头书 都有。

The self.included function is called when the module is included. It allows methods to be executed in the context of the base (where the module is included).

Modules that will be mixed with a class via the include or extend method could define something like a contructor or initializer method to the module. The module initializer method will be invoked at the time the module is mixed with a class. When a class extends a module the modules self.extended method will be invoked:

module Math
  def self.extended(base)
    # Initialize module.
  end
end
The self prefix indicates that the method is a static module level method. The base parameter in the static extended method will be either an instance object or class object of the class that extended the module depending whether you extend a object or class, respectively.

When a class includes a module the modules self.included method will be invoked.

module Stringify
  def self.included(base)
    # Initialize module.
  end
end
The base parameter will be a class object for the class that includes the module.

It is important to note that inside the included and extended initializer methods you can include and extend other modules, here is an example of that:

module Stringify
  def self.included(base)
    base.extend SomeOtherModule
  end
end

ruby新手表示很简单。

Class Bar
  def self.hello
    new.world # => self.new.world => Bar.new.world
  end

  def world
    puts "Hello, world"
  end
end

Bar.hello

@skandhas 我和他说笑呢,我的意思是他不翻书也改懂

#18楼 @jhjguxin 谢谢,懂了,类似include啊.这俩token没区别么

include和extend的区别是一个用于引入实例方法,一个用于引入类方法,中间两个module的命名都已经说的很清楚了

有区别,懂了~~,这题目出的真好

还有没学到的,继续看书。。

instance_method 已经过时了

元编程才学到这些东西

#26楼 @huacnlee 你说 include InstanceMethods 这种方法过时了吗?现在用什么?

事实上很多人都是先写rails,然后再学ruby的。。。 因为大多数学这个都是有经验的老程序猿了

module Foo
    def self.hello
        new.world
    end
    def world
        puts "Hello,world"
    end
end

class CInclude
    include Foo
end

class CExtend
    extend Foo
end

在CInclude这个类中,它对hello这个类方法怎么处理? 同样,对于CExtend来说,它怎么处理world这个实例方法?

是不是直接无视?

#28楼 @daqing 直接写实例方法在 module 里面,外面不包东西

#33楼 @huacnlee 确实再加一层InstanceMethods是多余的。

这代码编的真TMD经典. 难道是楼主编的吗?

建议不懂的同学, 可以直接去看Ruby编程语言, 这本书彻底读一遍, 以上代码涉及的细节, 就全都明白了.

我想起来了, Rails中用来初始化一个基类, 还有RSpec中, 大量使用这种办法, 在一个类混入一个特定模块时, 对这个类执行一些特殊初始化操作.

我觉得这就是Ruby可爱的地方. 很小的技俩, 实现了玄幻的功能.

#35楼 @zw963 是我写的,这种写法算是一种模式了吧,很多地方都是这样的。

呵呵,表示看懂了

原本想用上这个技巧的,不过回过头来发现,简单的代码还是用继承更方便

如果使用vim+snipmate.vim 的话。假设当前文件名为 foo.rb ,输入 mod 后敲 Tab,然后敲 3,就会有如下补全:

module Foo
  module ClassMethods

  end 

  module InstanceMethods

  end 

  def self.included(receiver)
    receiver.extend         ClassMethods
    receiver.send :include, InstanceMethods
  end 
end

刚看了self.included,回调的思想。

included里的代码可以更加简洁

base.extend, ClassMethods # or base.send :extend, ClassMethods
base.include, InstanceMethods

#20楼 @willmouse 你这样加了个注释瞬间明白了

需要 登录 后方可回复, 如果你还没有账号请点击这里 注册