`

Ruby的单例方法的疑惑

阅读更多
class B
  class<<self
    def hello
      puts "old"
    end
  end
end

class<<B
  unless self.respond_to? :hello
    def hello
      puts "new"
    end
  end
end
B.hello

执行结果为new
class B
  class<<self
    def hello
      puts "old"
    end
  end
end

class<<B
  unless B.respond_to? :hello
    def hello
      puts "new"
    end
  end
end
B.hello

执行结果为old

这几段代码的作用都是打开类B的单例类,判断是否定义了hello方法,如果未定义,则定义这个方法,但是第一段和第二段代码的执行结果大相径庭。再看两段代码
class B
  def self.hello
    puts "old"
  end
end

class<<B
  unless self.respond_to? :hello
    def hello
      puts "new"
    end
  end
end
B.hello

执行结果为new
class B
  def self.hello
    puts "old"
  end
end

class<<B
  unless B.respond_to? :hello
    def hello
      puts "new"
    end
  end
end
B.hello

输出为old
一样的结果 百思不得其解
分享到:
评论
4 楼 Ultraman84 2009-12-23  
这个问题已经有大大回答了,我引用以下吧 ,也可以结贴了
因为class X; end中的“环境”是X这个类自身,而class << X; end中的“环境”是X的eigenclass,一个“虚拟类”。所以你会经常看到Ruby元编程的代码里有这种东西:
Ruby代码
class Object  
  def eigenclass  
    class << self  
      self  
    end  
  end  
end  

这样可以获得一个对象的eigenclass。Ruby里类也是对象,而值对象是没有eigenclass的,所以会看到:
Irb代码
irb(main):001:0> class Object  
irb(main):002:1>   def eigenclass  
irb(main):003:2>     class << self; self; end  
irb(main):004:2>   end  
irb(main):005:1> end  
=> nil  
irb(main):006:0> e = Object.eigenclass  
=> #<Class:Object>  
irb(main):007:0> Object.is_a? Class  
=> true  
irb(main):008:0> Object.is_a? e  
=> true  
irb(main):009:0> 1.eigenclass  
TypeError: no virtual class for Fixnum  
        from (irb):3:in `eigenclass'  
        from (irb):9  
        from :0  


楼主提的问题就在于,
Ruby代码
class B 
  self 
end 

这里的self是指“B”类自己

Ruby代码
class B  
  class << self  # 1  
    self         # 2  
  end  
end  


这里,1的self是“B”类自己,而2的self是B的eigenclass。

Ruby代码
class << B  
  self  
end  


这里的self是B的eigenclass。

Irb代码 
irb(main):001:0> class B  
irb(main):002:1>   self  
irb(main):003:1> end  
=> B  
irb(main):004:0> class << B  
irb(main):005:1>   self  
irb(main):006:1> end  
=> #<Class:B>  



Irb代码
irb(main):001:0> class Object  
irb(main):002:1>   def eigenclass  
irb(main):003:2>     class << self; self; end  
irb(main):004:2>   end  
irb(main):005:1> end  
=> nil  
irb(main):006:0> class B  
irb(main):007:1>   def self.foo  
irb(main):008:2>     'foo'  
irb(main):009:2>   end  
irb(main):010:1>   class << self  
irb(main):011:2>     def bar  
irb(main):012:3>       'bar'  
irb(main):013:3>     end  
irb(main):014:2>   end  
irb(main):015:1> end  
=> nil  
irb(main):016:0> B.respond_to? :foo  
=> true  
irb(main):017:0> B.respond_to? :bar  
=> true  
irb(main):018:0> B.eigenclass.respond_to? :foo  
=> false  
irb(main):019:0> B.eigenclass.respond_to? :bar  
=> false  
irb(main):020:0> B.eigenclass.methods.grep /foo|bar/  
=> []  
irb(main):021:0> B.eigenclass.instance_methods.grep /foo|bar/  
=> ["bar", "foo"]  
irb(main):022:0> B.is_a? B.eigenclass  
=> true  


可以看到foo和bar都成为了B的eigenclass的instance_methods,而不在其methods之中。

在楼主给的代码中,由于B的eigenclass作为一个对象自己无法respond_to? :hello,而B作为B的eigenclass的实例则可以respond_to? :hello,所以就有楼主看到的行为了。

引用Yugui画的一张图来展示Ruby 1.8里的类层次与实例的关系:Metaclass hierarchy 1.8
(点击图左上角的all sizes)可以看到大图。
3 楼 boobmoom 2009-12-23  
看到了这个问题也想知道这是为什么

根据orange0513的提示

得知ruby中有一个单例类,或是单件类或叫metaclass 也有叫singletonclass 的

具体叫什么我不知道

在javaeye上搜到了一个几年前的贴子

讲得非常清楚

http://www.iteye.com/topic/20352

LZ可以去看看
2 楼 orez88 2009-12-22  
class B
end

class<<B
  def hello
    puts "old"
  end
    
  unless self.respond_to? :hello
    def hello
      puts "new"
    end
  end
end
puts B.hello

###################################

class B
end

class<<B
  def hello
    puts "old"
  end
  class << self
    def hello
      puts "old"
    end
  end
  unless self.respond_to? :hello
    def hello
      puts "new"
    end
  end
end
puts B.hello
1 楼 orange0513 2009-12-17  
你可以puts self看看。class << B打开的是B的单例类,而在类中定义的是该单例类的实例对象B的方法。所以#<Class:B>这个单例类本身就不能响应hello方法。
class B 
  class<<self 
    def hello 
      puts "old" 
    end 
  end 
end 
 
class<<B 
  unless self.respond_to? :hello
    puts self  #输出这里看看!
    def hello 
      puts "new" 
    end 
  end 
end

相关推荐

    Ruby 方法、类

    在Ruby中,方法和类是构建程序的基本元素,它们是实现代码重用和组织的关键概念。 ### 方法(Methods) 方法在Ruby中是可重复使用的代码块,它们接受参数,执行特定任务,并可能返回值。方法定义使用`def`关键字...

    Ruby语言的简单介绍及代码实现

    单例方法是Ruby中的一个重要特性,它允许为特定的对象定义专属的方法。在上述例子中,我们为 `mc` 实例定义了一个单例方法 `the_method`。当调用 `mc.the_method` 时,实际上执行的是单例方法而不是类方法。单例方法...

    Ruby-Functo是ruby中的可组合方法对象

    标题提到的“Ruby-Functo”就是Ruby中实现可组合方法对象的一个库,它为开发者提供了更灵活和模块化的代码组织方式。 Functo库的设计理念是让函数或方法像对象一样可以被操作、组合和复用。在传统的面向对象编程中...

    详解Ruby设计模式编程中对单例模式的运用

    在Ruby中,单例模式可以通过多种方式实现,但最常用的方法之一是利用内置的`Singleton`模块。接下来我们详细探讨几种不同的实现方案。 #### 使用`Singleton`模块 Ruby的标准库中包含了`Singleton`模块,它可以很...

    06Ruby 方法.docx

    ### Ruby 方法详解 #### Ruby 语言简介 Ruby 是一种动态、面向对象的脚本语言,以其简洁、清晰的语法著称。它支持多种编程范式,包括面向对象、命令式和函数式编程,并且拥有强大的元编程能力。Ruby 的设计哲学强调...

    Hello, Ruby World!

    - **定义**:单例方法是在特定对象实例上定义的方法,而不是在类级别定义的。 - **示例**:通过在特定对象上定义方法,可以为该对象提供独特的行为。 ##### 5. 常量与变量 - **常量**:Ruby中的常量以大写字母开头...

    ruby metaprograming

    单例方法是只存在于某个特定类的一个实例上的方法,而不是类的所有实例共享的方法。 **示例**: ```ruby class MyClass; end instance = MyClass.new instance.singleton_class.class_eval do def unique_method ...

    Ruby API 帮助文档.zip

    Ruby支持方法定义、方法调用、私有方法、单例方法和块作为参数。 5. **元编程**: Ruby的元编程能力非常强大,允许在运行时修改类和对象的行为。这得益于其反射API,例如`class_eval`、`instance_variable_get`等,...

    Ruby Ruby Ruby Ruby Ruby Ruby

    Ruby Ruby Ruby Ruby Ruby Ruby

    ruby+voodoo

    4. 方法定义:Ruby支持单例方法,可以在类实例上定义方法,增加了灵活性。 5. 元编程:Ruby的强大之处在于其元编程能力,可以在运行时修改或创建类和对象。 Voodoo框架或库可能涉及的知识点: 1. 自动化工具:如果...

    RubyUsers'Guide

    单例方法允许开发者为单个对象创建独立的方法,这在Ruby中是一个非常有用的功能。 11. 过程对象 Ruby中的过程对象是类似于其他语言中函数或过程的对象。 12. 初始化对象 Ruby中的对象初始化是一个重要的过程,它...

    笨方法学ruby-中文版

    《笨方法学Ruby》是针对初学者的一本中文教程,旨在通过实践性的学习方式帮助读者掌握Ruby编程语言。这本书的特点是强调动手实践,通过一系列的练习来深化对Ruby语法和编程概念的理解。以下是对该书内容及压缩包文件...

    编程资源:Ruby 编程的简要介绍.docx

    Ruby支持单例方法,即针对特定实例定义的方法,只对该实例有效。 - **代码示例**: ```ruby class MyClass def the_method "general method" end end mc = MyClass.new def mc.the_method "special for ...

    Ruby基础语法+Ruby变量与数据类型+Ruby控制结构+Ruby函数与方法+Ruby面向对象编程等全套教程

    Ruby函数与方法 Ruby面向对象编程 Ruby模块与包 Ruby错误处理 Ruby文件与I/O操作 Ruby正则表达式 Ruby网络编程 Ruby数据库交互 Ruby测试框架 RubyWeb框架Rails入门 Ruby高级特性 Ruby性能优化与最佳实践

    ruby2ruby.zip

    ruby2ruby 提供一些用来根据 RubyParser 兼容的 Sexps 轻松生成纯 Ruby 代码的方法。可在 Ruby 中轻松实现动态语言处理。 标签:ruby2ruby

    Ruby-rubybuild编译和安装Ruby

    Ruby是一种动态、开源的编程语言,以其简洁、优雅的语法和强大的元编程能力著称。在Ruby开发中,为了管理不同版本的Ruby环境,我们常常会使用到`rbenv`和`ruby-build`这两个工具。本文将详细介绍如何使用`ruby-build...

    中文版 Ruby 设计模式.pdf

    主要包括Ruby概述、使用模板方法变换算法、使用策略替换算法、通过观察器保持协调、通过迭代器遍历集合、使用命令模式完成任务、使用适配器填补空隙、使用装饰器改善对象、单例、使用工厂模式挑选正确的类、通过生成...

Global site tag (gtag.js) - Google Analytics