我正在尝试一些关于如何在内部声明类以及在声明类时会发生什么的代码。我知道在声明一个类时,会创建一个'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允许我以特定方式宣布课程?如果它不是一个类,那为什么它表现得像一个?
答案 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
的一个实例),你可以使用你想要的任何一种方法(尽管第一种方法通常只在特殊情况下使用)。