2

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

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

为什么会这样?

- -更新 - -

我试过了

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在上述情况下具有单例方法)

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

上面的代码进一步强化了类的假设,x因为它允许我创建新对象。if xwould have been an instance thennew会因错误而失败。

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

4

2 回答 2

4

Ruby 解释器只将大写字母开头的内容视为常量。这就是为什么你的“类”x不包括在Class.constants

从此:_

命名约定

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

由于类名应该是常量,因此x在您的代码中不是类的名称。它是一个包含一个类的变量,它恰好没有正确的分配名称。(正如@ZachKemp在他的回答中所建议的那样,您可以通过输入x.name并看到它返回来进行验证)nil

简而言之,在 Ruby 中,您不能为类命名以小写字符开头。

于 2013-07-08T18:32:50.040 回答
2

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

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

于 2013-07-08T18:34:09.990 回答