Класс Метод "Знать" имя класса в Ruby?

Я хочу, чтобы унаследованный класс ruby ​​ "знал" его имя класса с помощью метода класса. Это лучше всего иллюстрируется надуманным примером:

class Parent
  def self.whoami
    ??
  end
end

class Child < Parent
  #No code should be needed.
end

Итак, я должен был бы позвонить:

Parent.whomai

и ожидаем возврата "Родительского", я должен был бы позвонить:

Child.whoami

и ожидайте возвращения "Ребенка". У меня такое ощущение, что на обычных языках это может быть невозможно. Но модель метапрограммирования Ruby поразила меня раньше. Есть предположения? Спасибо заранее.

Ответы

Ответ 1

Метод класса - это метод, в котором КЛАСС является приемником, поэтому, чтобы найти объект, на который вызывается метод (что вы пытаетесь сделать здесь), просто проверьте значение self.

class Parent
  def self.whoami
    self
  end
end

class Child < Parent
end

puts Parent.whoami #=> Parent
puts Child.whoami #=> Child

Ответ 2

Метод получения имени класса (фактически, модуль) - это Module#name. Нет необходимости писать самостоятельно:

Parent.name # => 'Parent'
Child.name  # => 'Child'

Однако в Ruby действительно нет такой вещи, как "имя класса", как на некоторых других языках. В Ruby класс - это просто объект, как любой другой объект, который присваивается переменной, как и любая другая переменная.

Весь метод Module#name выполняет цикл через все константы в системе и проверяет, был ли модуль назначен кому-либо из них, и возвращает это имя константы или nil, если оно не может найти.

Итак, как и любой другой объект, "имя" класса действительно не что иное, как любая переменная, которую вы используете для ссылки на него.

Пример:

foo = Class.new
foo.name # => nil

Теперь "имя" класса foo. Однако Module#name возвращает nil, потому что foo не является константой.

bar = foo
bar.name # => nil

Теперь "имя" класса равно как foo и bar, но Module#name явно все еще возвращает nil.

BAZ = foo
foo.name # => 'BAZ'

Теперь, поскольку класс был назначен константе, это имя константы будет считаться именем класса & hellip;

BAZ = nil
foo.name # => 'BAZ'

& hellip; даже после того, как константа была назначена на что-то другое и & hellip;

QUX = foo
QUX.name # => 'BAZ'

& hellip; даже после того, как класс был назначен другой константе.

Module#to_s использует Module#name, если это не nil, поэтому, чтобы напечатать имя класса, вы просто выполняете

puts Parent

На самом деле нет абсолютно никакой потребности во всех сложных пухах в других ответах.

Ответ 3

Не то, что вам скажет Parent.class?

class Parent
  def self.whoami
    self.to_s
  end
end

class Child < Parent
end

> Parent.whoami
=> "Parent"
> Child.whoami
=> "Child"

Ответ 4

Предположим, вы класс:

class ABC
 def self.some_method
   self.name #it will return 'ABC'
   self.name.constantize #it will return ABC
 end
end