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

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

经常有初学者问,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 你这样加了个注释瞬间明白了

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