在Ruby中"知道"类名的类方法?

JP *_*son 14 ruby inheritance metaprogramming

我希望继承的ruby类通过类方法"知道"它的类名.一个人为的例子可以很好地说明这一点:

class Parent
  def self.whoami
    ??
  end
end

class Child < Parent
  #No code should be needed.
end
Run Code Online (Sandbox Code Playgroud)

所以我应该可以致电:

Parent.whomai
Run Code Online (Sandbox Code Playgroud)

并期望返回"父母",然后我应该可以致电:

Child.whoami
Run Code Online (Sandbox Code Playgroud)

并期望回归"孩子"我觉得在传统语言中这可能是不可能的.但Ruby的元编程模型以前让我感到惊讶.有什么想法吗?提前致谢.

hor*_*guy 21

类方法是CLASS是接收器的方法,因此要查找调用该方法的对象(您在此处尝试执行的操作)只需检查其值self.

class Parent
  def self.whoami
    self
  end
end

class Child < Parent
end

puts Parent.whoami #=> Parent
puts Child.whoami #=> Child
Run Code Online (Sandbox Code Playgroud)


Jör*_*tag 15

获取类名称(实际上是模块)的方法就是Module#name.没有必要自己编写:

Parent.name # => 'Parent'
Child.name  # => 'Child'
Run Code Online (Sandbox Code Playgroud)

但是,在Ruby中,实际上没有像其他语言那样的"类名".在Ruby中,类只是一个像任何其他对象一样的对象,它像任何其他变量一样被赋值给变量.

所有Module#name方法都是循环遍历系统中的所有常量,并检查模块是否已分配给它们中的任何一个,并返回该常量的名称或者nil它是否找不到任何名称.

所以,就像任何其他对象一样,类的"名称" 实际上只不过是用于引用它的任何变量.

例:

foo = Class.new
foo.name # => nil
Run Code Online (Sandbox Code Playgroud)

现在,班级的"名称"是foo.但是,Module#name返回nil,因为foo不是常数.

bar = foo
bar.name # => nil
Run Code Online (Sandbox Code Playgroud)

现在,这个类的"名"是 foobar,但Module#name显然还是返回nil.

BAZ = foo
foo.name # => 'BAZ'
Run Code Online (Sandbox Code Playgroud)

现在,由于该类已被赋值为常量,该常量的名称将被视为该类的名称...

BAZ = nil
foo.name # => 'BAZ'
Run Code Online (Sandbox Code Playgroud)

...即使在将常数分配给不同的东西之后......

QUX = foo
QUX.name # => 'BAZ'
Run Code Online (Sandbox Code Playgroud)

......甚至在课程被分配到不同的常数之后.

Module#to_sModule#name如果不是nil,则使用,打印类的名称,你就是这样做的

puts Parent
Run Code Online (Sandbox Code Playgroud)

在其他答案中,绝对不需要所有复杂的绒毛.