ruby对象模型和类声明

时间:2013-07-08 18:24:55

标签: ruby

我正在尝试一些关于如何在内部声明类以及在声明类时会发生什么的代码。我知道在声明一个类时,会创建一个'Class'对象,并创建一个带有声明类名称的常量。例如

MyClass = Class.new
MyClass.class => Class
MyClass.superclass => Object
Class.constants.include? :MyClass => true

我也试过

x = Class.new => #<Class:0xd886938> 
x.class => Class 
x.superclass => Object 
Class.constants.include? :x => false #why so???

这意味着'x'是一个类。我很困惑原因

class x
  def say_hi 
    'hi'
  end
end

给出

SyntaxError: (irb):121: class/module name must be CONSTANT

为什么会这样?

--- --- UPDATE

我试过

def x.x_method
  'x class method'
end

并且做了

x.methods.include? :x_method => true

类似地

x.singleton_methods.include? :x_method => true

主要是

x.methods - MyClass.methods => [:x_method]

以上几行指出x是一个类,因为它是类Class的对象。由于所有用户定义的类都是类Class的对象,因此它们的初始方法也应该相同,除非为特定类声明了一些单例方法(在上述情况下x具有单例方法)< / p>

x => #<Class:0xd886938>
obj_x = x.new  => #<#<Class:0xd886938>:0xd30caac> 
obj_x.class => #<Class:0xd886938> 

上面的代码进一步强化了x是一个类的假设,因为它允许我创建新对象。如果x是一个实例,那么new将失败并出现错误。

我的问题是,为什么ruby允许我以特定方式宣布课程?如果它不是一个类,那为什么它表现得像一个?

2 个答案:

答案 0 :(得分:4)

Ruby解释器只看到以大写字母作为常量开头的东西。这就是为什么您的“课堂”x未包含在Class.constants

来自This

  

命名约定

     

Ruby强制执行一些命名约定。如果标识符以a开头   大写字母,它是一个常数。如果它以美元符号($)开头,   它是一个全局变量。如果它以@开头,那么它就是一个实例   变量。如果它以@@开头,那么它是一个类变量。

由于类名应该是常量,因此代码中的x不是类的名称。它是一个包含类的变量,恰好没有正确的指定名称。 (根据@ZachKemp的回答,您可以输入x.name并看到它返回nil进行验证

简而言之,您不能为类提供一个以Ruby中的小写字符开头的名称。

答案 1 :(得分:2)

正如您所发现的,您可以将类视为Ruby中的第一类对象。在您创建一个新类x = Class.new的情况下,您已将一个类实例对象分配给一个变量,这与给它一个名称不同(您可以发送查询方法x.name验证名称是nil)。然后,您可以将该变量分配给常量(MyClass = x)以赋予其永久名称。

class声明是一个期望以常量开头的关键字。这两种创建类的方法都创建了相同的东西(Class的一个实例),你可以使用你想要的任何一种方法(尽管第一种方法通常只在特殊情况下使用)。