2013-07-08 28 views
2

我在尝试一些关于如何在内部声明类以及声明类时会发生什么的代码。我得知,当一个类被声明时,一个'Class'对象被创建并且一个常量与被声明的类的名字被创建。例如ruby​​对象模型和类声明

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' 是一个类。 I M困惑的原因

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具有单方法)

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

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

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

+0

@mbratch但一切都是红宝石是一个对象。即Class类的一个实例。比如说,String类是Class类的一个实例。 –

+1

x是对一个类的引用。你不能从它的名字访问这个类,因为它没有它,因为ruby期望所有的类名都是常量,而你没有提供它。因此'SyntaxError:(irb):121:class/module name必须是CONSTANT'错误。你可以访问你创建的这个类的唯一方法就是你存储在x中的这个引用。 – Cezar

+0

尝试下面的命令,看看它们与'x'有什么不同。而不是以#的形式查看对任意未命名类的引用,这是'x'引用的内容,您将看到类名。 'obj_MyClass = MyClass.new'和'obj_MyClass.class' – Cezar

回答

4

Ruby解释器只能看到以大写字母开头的东西作为常量。这就是为什么不包括你的“类” xClass.constants

This

Naming conventions

Ruby enforces some naming conventions. If an identifier starts with a capital letter, it is a constant. If it starts with a dollar sign ($), it is a global variable. If it starts with @, it is an instance variable. If it starts with @@, it is a class variable.

由于类名应该是常数,x在你的代码是不是类的名称。它是一个持有类的变量,恰好没有正确的分配名称。 (你可以通过输入x.name,看到它返回nil验证,作为对他的回答提出由@ZachKemp

总之,你不能给一个类,与Ruby的小写字母开头的名称。

2

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

class声明是一个关键字,需要一个常量开始。两种创建类的方法创建相同的事物(Class的一个实例),并且您可以使用任意一种方法(尽管第一种方法通常只在特殊情况下使用)。

+1

有趣...'MyClass = x'改变'x'的行为.. – jozefg

+0

哪种行为? –

+0

'x.name'从'nil'变成'MyClass'。这是有道理的,但认为赋值应该影响赋值的语义很奇怪 – jozefg