Синтаксис методов класса в ruby - PullRequest
3 голосов
/ 26 ноября 2011

Рубиновая книга, которую я читаю, немного смутила меня.Если я сделаю следующее, я пойму полностью, почему код выдает ошибку:

class Person
  def show_name
    puts @name
  end
end

person = Person.new
person.show_name
Person.show_name   #(note the capital P) this line falls over

Он выдает ошибку, утверждая, что у класса Person нет метода с именем show_name, потому что это метод экземпляра.Я понимаю это полностью.Затем в этом примере книга выдает:

class Class
  def add_accessor(accessor_name)
    self.class_eval %Q{attr_accessor :#{accessor_name}}
  end
end

class Person
end

person = Person.new
Person.add_accessor :name    #note the capital P
Person.add_accessor :age     #capital P here too

person.name = "Mikey"
person.age = 30

puts person.name

и продолжает утверждать, насколько круто, что вы можете динамически добавлять методы в классы.Чего я не понимаю, так это почему мне вдруг разрешают вызывать метод add_accessor как метод класса (с большой буквы P), если сам метод не определен как таковой?Я думал, что все методы класса должны быть объявлены так?

class Math
  def self.PI
    3.141
  end
end

puts Math.PI

Кто-нибудь может меня просветить?

Ответы [ 4 ]

2 голосов
/ 26 ноября 2011

Классы Ruby - это объекты, подобные всем остальным.Ваш класс Person действительно является объектом класса Class, который, в свою очередь, наследуется от класса Module.Когда вы добавляете метод к классу Class как метод экземпляра, вы предоставляете новый метод для всех классов.Если бы вы объявили это с def лично, это не могло бы быть вызвано без объекта.Чтобы добавить методы класса для одного класса, но не для всех, необходимо добавить имя метода к себе или к имени класса:

class Person
    def instance_method
    end
    def self.class_method
    end
    def Person.other_class_method
    end
end

Когда вы объявляете метод как self.class_method, вы объявляете свой методбыть одноэлементным методом на объекте класса.self в объявлении класса или модуля относится к объекту класса, поэтому self. и Person. одинаковы.Имея дело с Ruby, просто помните, все является объектом, у всех есть методы.В Ruby также нет функций, несмотря на появление противоположного.Методы и объекты всегда.

1 голос
/ 26 ноября 2011

Посмотрите на это:

person.instance_of?(Person) #=> true
Person.instance_of?(Class)  #=> true

Вы определили метод экземпляра add_accessor для всех экземпляров класса Class, поэтому класс Person может использовать этот метод, поскольку он является экземпляром Class.

Я рекомендую вам взглянуть на метапрограммирование и Ruby Object Model.

Да, это помогает

1 голос
/ 26 ноября 2011

Вы расширяете класс Class, и все ваши классы, такие как Person, являются экземплярами Class (Да, классы являются экземплярами класса Class. Это обычные объекты).

Поэтому, когда вы вызываете Person.add_accessor, вы вызываете метод экземпляра Class#add_accessor.

0 голосов
/ 26 ноября 2011

потому что Person (с заглавной буквой P) является экземпляром класса Class.

Добро пожаловать на сайт PullRequest, где вы можете задавать вопросы и получать ответы от других членов сообщества.
...