Class :: new и Class # new тоже самое? - PullRequest
2 голосов
/ 09 мая 2019

Класс Class имеет версию метода класса new и версию метода экземпляра new.Но поскольку Class является экземпляром Class, это не делает версию метода класса new версией метода экземпляра new?

Когда я вижу следующее

>> Class.new
=> #<Class:0x00007fca601fe898>

Я думаю, что объект Class является экземпляром Class, поэтому new является методом экземпляра класса Class.Скорее, new является методом класса Class.

Ответы [ 2 ]

5 голосов
/ 09 мая 2019

Класс :: новый и Класс # новый не совпадают.

Class::new Создает новый анонимный (неназванный) класс с заданным суперкласс.
Class.new Вызывает выделение для создания нового объекта класса, затем вызывает метод инициализации этого объекта, передавая это аргументы.

Если вы нажмете на переключение источника в ссылках на документы выше, вы увидите только это.

В основном Class.new является инициализатором по умолчанию, который наследует каждый другой класс в ruby.
Class::new создает новый анонимный класс.

1 голос
/ 10 мая 2019

Class::new и Class#new одинаковы.

Как и методы new в других классах (String.new, Array.new и т. Д.), Class.new разрешается до Class#new. Классы Ruby обычно не предоставляют свой собственный метод класса new. Мы можем легко подтвердить это, заменив Class#new:

String.new #=> ""
Array.new  #=> []
Class.new  #=> #<Class:0x00007fef2517f5e0>

class Class
  def new(*args)
    "it's me, Class#new"
  end
end

String.new #=> "it's me, Class#new"
Array.new  #=> "it's me, Class#new"
Class.new  #=> "it's me, Class#new"

Исходная реализация Class#new создает новый объект, вызывая метод allocate получателя и вызывая метод initialize этого объекта (передавая аргументы), что-то вроде:

class Class
  def new(*args, &block)
    obj = allocate
    obj.send(:initialize, *args, &block)
    obj
  end
end

Итак, Class#new - это простой шаблонный метод - фактическая работа выполняется allocate и initialize.

Мы можем определить разницу, проверив initialize - ее владельцем является Class для Class#initialize, но BasicObject для их экземпляров:

Class.instance_method(:initialize).owner
#=> Class

Class.new.instance_method(:initialize).owner
#=> BasicObject

Путаница проистекает из документации, которая показывает #initialize как ::new (что удобно, потому что мы обычно вызываем new и редко, если вообще когда-либо, вызываем initialize напрямую). Поэтому, если вы откроете документы для Class::new и нажмете «toogle source» , вы посмотрите на реализацию для Class#initialize (или rb_class_initialize, как она вызывается в C)

Единственный известный мне класс, который фактически переопределяет метод класса new, это Struct, то есть Struct::new:

Struct.method(:new).owner        #=> #<Class:Struct>
Struct.method(:new).super_method #=> #<Method: Class#new>
Добро пожаловать на сайт PullRequest, где вы можете задавать вопросы и получать ответы от других членов сообщества.
...