2016-10-25 3 views
4

Давайте нормальный класс рубин:Метод экземпляра Ruby класса def initialize: метод экземпляра или класса?

class Person 
    attr_accessor :name 
    def initialize name 
    @name = name 
    end 
end 

bob = Person.new("bob") 

Мой вопрос характер Initialize. Вот что, new явно метод класса, но мне кажется, что initialize - это метод экземпляра (не класс), который вызывается в экземпляре, созданном КОГДА вызывается метод класса new.

Есть ли у меня это право? Или может кто-то пролить новый свет? Я выполнил некоторые поисковые запросы Google и не нашел никакой ясности.

+1

Это своего рода уникальный - вы можете получить доступ к области экземпляров метода, но, как вы говорите, это можно назвать методом класса. Обратите внимание, что инициализация не будет вызываться, если вы определяете 'def self.new'. –

+0

означает, что это вызвано в результате вызова метода 'new'? или это действительно «новый» метод? –

+0

Да. Также обратите внимание, что [Module # attr_accessor] (http://ruby-doc.org/core-2.0.0/Module.html#method-i-attr_accessor) также является методом класса, который создает два метода экземпляра (здесь 'name' и 'name ='). –

ответ

3

Затем новый объект инициализируется (то есть, когда вы звоните new по классу), это то, что эффективно вызывается этот метод:

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

В стандартной реализации Ruby, этот метод реализован в C, но well documented.

Чтобы понять, что здесь происходит, вы должны знать, что в Ruby даже классы являются объектами (они являются экземплярами или классом Class). Таким образом, при вызове new на ваш класс Person вы фактически вызываете метод new на экземпляр объекта Class.

Как вы можете видеть, ваш класс Person предлагает метод выделения памяти для нового экземпляра. После выделения памяти метод new вызывает initialize только что созданного экземпляра.

+0

этот фрагмент кода идеален, спасибо –

+0

В действительности 'initialize' является' private' по умолчанию, поэтому средняя строка * действительно * больше похожа на 'obj.send (: initialize, * args, & block)', но конечный результат тот же. Если вы когда-либо использовали Objective-C, это должно выглядеть знакомым, потому что 'Foo.alloc.init' - это, по сути, то, как вы создаете объект. –

+0

Спасибо @ JörgWMittag. Я исправил код и узнал немного больше о том, как работает диспетчеризация методов в C-Ruby. –

Смежные вопросы