Centos系统下载大全 | Redhat系统下载大全 | Windows2012系统下载大全 | Windows2008系统下载大全| CMS教程 | 网站地图 51运维网-专注Linux/Unix系统安全运维!
当前位置:51运维网 > 编程 > Ruby > 正文

理解Ruby2.0中方法是如何查找与执行(1)

时间:2015-01-29 11:51 来源:网络整理 作者:51ou.com 阅读:

  预先介绍Ruby2.0是一个好的机会去回顾如何精确的用Ruby去树立方法调用。

  理解查找方法对于掌握Ruby的层次类是很有必要的。我准备的这篇文章有很多的代码例子;你需要用Ruby 1.9.2 或者 更新的版本去调试运行大部分的例子,这有一个预先准备好的,它只能够运行在Ruby2.0.0

  类层次结构

  让我们以基类的继承这一经典的例子开始吧

  class Animal  
    def initialize(name)  
      @name = name  
    end  
    def info  
      puts "I'm a #{self.class}."
      puts "My name is '#{@name}'."
    end  
  end  
  class Dog < Animal  
    def info  
      puts "I #{make_noise}."
  super
    end  
    def make_noise  
  'bark "Woof woof"'
    end  
  end  
  lassie = Dog.new"Lassie"
  lassie.info  
  # => I bark "Woof woof".  
  #    I'm a dog.  
  #    My name is 'Lassie'.

  在这个例子中,狗这个类继承于动物类. 我们把动物类称之为狗的超级类:

  Dog.superclass # => Animal 

  记住这个方法 Dog#info 调用超级类,这个特殊的关键字执行了后面接着的这个层次的定义,像这个例子  Animal#info 这个类可以用继承类的属性

  Dog.ancestors # => [Dog, Animal, Object, Kernel, BasicObject] 

  继承类不以Animal结尾时很令人感兴趣的地方

  Animal.superclass # => Object 

  这个Animal类的申明相当于之前写了一个Animal类的对象

  这就是为什么动物药拥有比make_noise更多的方法,尤其反思的方法像是 respond_to?方法等等:

  lassie.respond_to? :upcase # => false
  lassie.methods  
   # => [:nil?, :===, :=~, :!~, :eql?, :hash, :<=>, :class, :singleton_class, ...] 

  因此怎么引出内核和基本对象呢?待会我将回谈到内核,事实上并不会说太多的基本对象之外的东西只有有限数量的方法并且会以所有类的层次结构收尾。

  # BasicObject is the end of the line:  
  Object.superclass # => BasicObject  
  BasicObject.superclass # => nil  
  # It has very few methods:  
  Object.instance_methods.size # => 54
  BasicObject.instance_methods.size # => 8

  

类是形成一棵树的根茎所在

  Mixins

  虽然Ruby只支持单根继承(也就是说,一个类只有一个超类),但它支持 mixins. mixin是一组可以包含到其他类的方法。在Ruby,实现为Module类:

  module Mamal  
    def info  
      puts "I'm a mamal"
  super
    end  
  end  
  Mamal.class # => Module 

  要在我们的Dog类中加入这个功能,我们可以用include 或者 prepend. 它们会插入这个module在Dog类之前或者之后:

  class Dog  
    prepend Mamal  
  end  
  lassie = Dog.new"Lassie"
  lassie.info  
  # => I'm a mamal.  
  #    I bark "Woof woof".  
  #    I'm a dog.  
  #    My name is 'Lassie'.
  Dog.ancestors # => [Mamal, Dog, Animal, Object, ...] 

  如果这个module被include到Dog类,而不是prepend到Dog类,效果类似,但是输出的顺序不一样,你能猜到结果和祖先(ancestors)输出的循序吗?  点击这里看结果  .

  你可以随意包含任意多个 include 和 prepend 的module。module还可以include和 prepende 其他module。当你不确定module和类得继承体系时,马上调用ancestors搞清楚。

  单件类

  在Ruby里, 在module和类得体系中,只有一个额外的层。任意对象可以有一个特殊的类优先于任何事:单件类(singleton class)

  下面有个例子:

  scooby = Dog.new"Scooby-Doo"
  class << scooby  
    def make_noise  
  'howl "Scooby-Dooby-Doo!"'
    end  
  end  
  scooby.info  
  # => I'm a mamal.  
  #    I howl "Scooby-Dooby-Doo!".  
  #    I'm a dog.  
  #    My name is 'Scooby-Doo'.

  请注意复吠叫那部分(I bark "Woof woof".)被史酷比特殊的嚎叫()代替了I howl "Scooby-Dooby-Doo!".那这不会影响Dog类得其他实例。

  "class << scooby"是重新打开一个对象的单件类的特殊记法。还有一个方法可以定义单件方法:

  # 和上面的例子等同:
  def scooby.make_noise  
  'howl "Scooby-Dooby-Doo!"'
  end 

  单件类是个真正的类,可以通过调用singleton_class来访问:

  # 单件类有个特别的名字:
  scooby.singleton_class # => #<Class:#<Dog:0x00000100a0a8d8>>  
  # 单件类是个真正的类:
  scooby.singleton_class.is_a?(Class) # => true 
  # 我们可以得到它实例方法的列表:
  scooby.singleton_class.instance_methods(false) # => [:make_noise] 

  所有Ruby对象都可以有单件类,包括类它们自己,甚至单件类自己也可以有单件类。

  这听起来有些疯狂...那不是需要无数个单件类啊?某种意义上讲,是的,但是Ruby会在他们需要的时候再去创建。

  虽然上个例子是使用Dog类的一个实例的单件类。单更见的用在类上。. 实际上, "  类方法  " 就是单件类得方法。例如,attr_accessor 是Module单件类的一个实例方法。 Ruby on Rails 中的 ActiveRecord::Base 类有很多这样的方法例如 has_many, validates_presence_of,  等等。下面可以看到ActiveRecord::Base的单件类的方法个数:

  Module.singleton_class  
        .private_instance_methods  
        .include?(:attr_accessor) # => true
  require 'active_record'
  ActiveRecord::Base.singleton_method  
                    .instance_methods(false)  
                    .size  # => 170 

  单件类的名字来源于,他们有且只能有一个实例:

  scooby2 = scooby.singleton_class.new 
    # => TypeError: can't create instance of singleton class

  因为同样的原因,你不能直接继承一个单件类:

  class Scoobies < scooby.singleton_class  
    # ...  
  end  
  # => TypeError: can't make subclass of singleton class

  另一方面,单件类有一个完整的类体系。

  对于对象;来说,我们有:

  scooby.singleton_class.superclass == scooby.class == Dog  
   # => true, as for most objects 

  对于类来说,Ruby会自动设置超类,所以穿越超类或者单点类的不同路径都相等:

  Dog.singleton_class.superclass == Dog.superclass.singleton_class  
   # => true, as for any Class

  这意味着Dog继承Animal的实例方法以及它的单件方法。

  为了彻底搞晕大家,我最后写下个extend的注解。它可以看做在被扩展对象的单件类include一个module的简写include 或者 prepend. 它们会插入这个module在Dog类之前或者之后:

  class Dog  
    prepend Mamal  
  end  
  lassie = Dog.new"Lassie"
  lassie.info  
  # => I'm a mamal.  
  #    I bark "Woof woof".  
  #    I'm a dog.  
  #    My name is 'Lassie'.
  Dog.ancestors # => [Mamal, Dog, Animal, Object, ...] 

  如果这个module被include到Dog类,而不是prepend到Dog类,效果类似,但是输出的顺序不一样,你能猜到结果和祖先(ancestors)输出的循序吗?  点击这里看结果  .

  你可以随意包含任意多个 include 和 prepend 的module。module还可以include和 prepende 其他module。当你不确定module和类得继承体系时,马上调用ancestors搞清楚。

  单件类

  在Ruby里, 在module和类得体系中,只有一个额外的层。任意对象可以有一个特殊的类优先于任何事:单件类(singleton class)

  下面有个例子:

  scooby = Dog.new"Scooby-Doo"
  class << scooby  
    def make_noise  
  'howl "Scooby-Dooby-Doo!"'
    end  
  end  
  scooby.info  
  # => I'm a mamal.  
  #    I howl "Scooby-Dooby-Doo!".  
  #    I'm a dog.  
  #    My name is 'Scooby-Doo'.

  请注意复吠叫那部分(I bark "Woof woof".)被史酷比特殊的嚎叫()代替了I howl "Scooby-Dooby-Doo!".那这不会影响Dog类得其他实例。

  "class << scooby"是重新打开一个对象的单件类的特殊记法。还有一个方法可以定义单件方法:

  # 和上面的例子等同:
  def scooby.make_noise  
  'howl "Scooby-Dooby-Doo!"'
  end 

  单件类是个真正的类,可以通过调用singleton_class来访问:

感谢您对【51运维网 http://www.51ou.com/】的支持,我们为您免费提供《理解Ruby2.0中方法是如何查找与执行(1)》技术文章,《理解Ruby2.0中方法是如何查找与执行(1)》详细使用和说明,有时《理解Ruby2.0中方法是如何查找与执行(1)》可能不完善、敬请谅解!如果《理解Ruby2.0中方法是如何查找与执行(1)》有错误请给我们留言,我们将尽快修复文章错误,如果您觉得本站不错,请分享给周围的朋友!谢谢!

顶一下
(0)
0%
踩一下
(0)
0%
发表评论
请自觉遵守互联网相关的政策法规,严禁发布色情、暴力、反动的言论。
验证码:点击我更换图片