singleton_class - иерархия классов ruby




класс<< self idiom в Ruby (4)

Какой класс << вещь:

class Hi
  self #=> Hi
  class << self #same as 'class << Hi'
    self #=> #<Class:Hi>
    self == Hi.singleton_class #=> true
  end
end

[он делает self == thing.singleton_class в контексте своего блока] .

Что такое thing.singleton_class?

hi = String.new
def hi.a
end

hi.class.instance_methods.include? :a #=> false
hi.singleton_class.instance_methods.include? :a #=> true

Объект hi наследует свои #singleton_class.instance_methods #methods от его #singleton_class.instance_methods а затем из его #class.instance_methods .
Здесь мы приводили метод экземпляра однопользовательского класса hi :a . Это могло быть сделано с классом << hi вместо этого.
hi 's #singleton_class имеет все методы экземпляра hi 's #class и, возможно, еще несколько ( :a здесь).

[методы экземпляра объекта #class и #singleton_class могут применяться непосредственно к предмету. когда рубин видит вещь.a, он сначала ищет: определение метода в thing.singleton_class.instance_methods, а затем в thing.class.instance_methods]

Кстати, они называют одноэлементным классом класса == metaclass == eigenclass .

Что делает class << self в Ruby?


В этом integralist.co.uk/posts/eigenclass.html я нашел супер простое объяснение в class << self , Eigenclass и разных типах methods .

В Ruby существует три типа методов, которые могут применяться к классу:

  1. Методы экземпляра
  2. Одиночные методы
  3. Методы класса

Методы экземпляров и методы класса почти аналогичны их одноименным в других языках программирования.

class Foo  
  def an_instance_method  
    puts "I am an instance method"  
  end  
  def self.a_class_method  
    puts "I am a class method"  
  end  
end

foo = Foo.new

def foo.a_singleton_method
  puts "I am a singletone method"
end

Другой способ доступа к Eigenclass (который включает в себя методы singleton) имеет следующий синтаксис ( class << ):

foo = Foo.new

class << foo
  def a_singleton_method
    puts "I am a singleton method"
  end
end

теперь вы можете определить одноэлементный метод для self который сам является классом Foo в этом контексте:

class Foo
  class << self
    def a_singleton_and_class_method
      puts "I am a singleton method for self and a class method for Foo"
    end
  end
end

Обычно методы экземпляра - это глобальные методы. Это означает, что они доступны во всех экземплярах класса, на котором они были определены. Напротив, однотонный метод реализуется на одном объекте.

Способы хранения Ruby в классах и всех методах должны быть связаны с классом. Объект, на котором определен одноэлементный метод, не является классом (это экземпляр класса). Если только классы могут хранить методы, как объект может хранить одноэлементный метод? Когда создается однопользовательский метод, Ruby автоматически создает анонимный класс для хранения этого метода. Эти анонимные классы называются метаклассами, также известными как одноэлементные классы или eigenclasses. Метод singleton связан с метаклассом, который, в свою очередь, связан с объектом, на котором был определен метод singleton.

Если несколько одиночных методов определены внутри одного объекта, все они хранятся в одном метаклассе.

class Zen
end

z1 = Zen.new
z2 = Zen.new

class << z1
  def say_hello
    puts "Hello!"
  end
end

z1.say_hello    # Output: Hello!
z2.say_hello    # Output: NoMethodError: undefined method `say_hello'…

В приведенном выше примере класс << z1 изменяет текущее «я», чтобы указать на метакласс объекта z1; то он определяет метод say_hello в метаклассе.

Классы также являются объектами (экземплярами встроенного класса Class). Методы класса - это не что иное, как одиночные методы, связанные с объектом класса.

class Zabuton
  class << self
    def stuff
      puts "Stuffing zabuton…"
    end
  end
end

Все объекты могут иметь метаклассы. Это означает, что классы также могут иметь метаклассы. В приведенном выше примере класс << self изменяет self, поэтому он указывает на метакласс класса Zabuton. Когда метод определен без явного приемника (класс / объект, на котором будет определяться метод), он неявно определяется в текущей области, то есть текущее значение self. Следовательно, метод stuff определяется в метаклассе класса Zabuton. Вышеприведенный пример - это еще один способ определения метода класса. IMHO, лучше использовать синтаксис def self.my_new_clas_method для определения методов класса, поскольку он делает код более понятным. Вышеприведенный пример был включен, поэтому мы понимаем, что происходит, когда мы сталкиваемся с классом << self syntax.

Дополнительную информацию можно найти на этой странице о Ruby Classes .


Фактически, если вы пишете какие-либо C-расширения для ваших проектов Ruby, существует только один способ определения метода модуля.

rb_define_singleton_method

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

Сначала объекты.

foo = Object.new

Могу ли я создать метод для foo?

Конечно

def foo.hello
 'hello'
end

Что мне делать с этим?

foo.hello
 ==>"hello"

Еще один объект.

foo.methods

Вы получаете все методы Object плюс ваш новый.

def foo.self
 self
end

foo.self

Просто объект foo.

Попробуйте посмотреть, что произойдет, если вы сделаете foo из других объектов, таких как Class и Module. Примеры из всех ответов хороши, но вы должны работать с различными идеями или концепциями, чтобы действительно понять, что происходит с тем, как написан код. Итак, теперь у вас есть много условий, на которые нужно смотреть.

Singleton, Class, Module, self, Object и Eigenclass были подняты, но Ruby не назвал Object Models таким образом. Это больше похоже на Metaclass. Ричард или __why показывает вам эту идею здесь. viewsourcecode.org/why/hacking/seeingMetaclassesClearly.html И если удары вас прочь, попробуйте найти объект Ruby Object Model в поиске. Два видео, которые я знаю на YouTube, - это Дэйв Томас и Питер Купер. Они тоже пытаются объяснить эту концепцию. Дэйву потребовалось долгое время, чтобы не волноваться. Я все еще работаю над этим. Зачем еще я здесь? Спасибо за ваш вопрос. Также взгляните на стандартную библиотеку. Он имеет модуль Singleton, как FYI.

Это очень хорошо. https://www.youtube.com/watch?v=i4uiyWA8eFk





singleton