2013-04-03 2 views
2

Как ссылаться на класс внутри статического метода?Ruby динамически создает экземпляр класса

class Car 
    def self.new_from_xml(xml) 
    instance = self.class.new 
    #do some stuff with xml 
    instance 
    end 
end 

class Mercedes < Car 
end 

class Porsche < Car 
end 

IRB:

Mercedes.new_from_xml(somedata) # Output is #<Class:...>, should be #<Mercedes:...> 
Porsche.new_from_xml(somedata) # Output is #<Class:...>, should be #<Porsche:...> 

ответ

4

Вместо

instance=self.class.new 

просто написать

instance = new 

Почему это?

Ну, в первую очередь, вы должны понимать, что вы вызываете метод класса, таким образом, вы уже на уровне класса. Метод .new - это метод класса, поэтому вы можете вызвать его напрямую, не вызывая self.class.new.

Почему именно self.class.new return Class?

Поскольку класс класса Car является классом (я знаю, звучит странно;), потому что классы в Ruby являются экземплярами класса.

Это на самом деле довольно глубокая концепция, я рекомендую вам прочитать об этом больше. Одна хорошая рекомендация, которую я прочитал, - это книга Метапрограммирования Руби Паоло Перротты (ISBN-10: 1934356476) [1].

  1. http://www.amazon.com/Metaprogramming-Ruby-Program-Like-Pros/dp/1934356476
2

Поскольку вы уже в методе класса, вы должны использовать self.new (или просто new как @tokland писал) вместо self.class.new:

class Car 
    def self.new_from_xml(xml) 
     instance = new 
     #do some stuff with xml 
    end 
end 

class Mercedes < Car 
end 

class Porsche < Car 
end 

p Mercedes.new_from_xml(nil) #=> #<Mercedes:0x007f042d0db208> 
p Porsche.new_from_xml(nil) #=> #<Porsche:0x007f042d0db118> 

От комментария к этому ответу: Почему я сам. класс ссылки на класс? В чем тут логика?

Внутри блока класса self ссылается на класс редактируется:

class Car 
    puts self #=> writes Car 
end 

Использование def self.new_from_xml это как если вы объявляете def Car.new_from_xml, то есть метод Car объекта (который является экземпляром Class); поэтому внутри new_from_xmlself совпадает с Car.

+0

или просто 'new'. Кроме того, вы можете исправить унииоматический стиль (пробелы, отступы) вопроса :-) – tokland

+0

@tokland right ;-) – mdesantis

+0

Спасибо. Это сработало. Почему ссылка self.class на класс? Какая здесь логика? – gorootde