Наследование класса Ruby: что такое `<<` (вдвое меньше)?

class << Awesomeness

Что это за << для? Я искал, но результаты только говорят мне о конкатенации строк...

Ответ 1

Хотя верно, что class << something является синтаксисом для одноэлементного класса, как сказал кто-то другой, он чаще всего используется для определения методов класса в определении класса. Но эти два соглашения последовательны. Вот как.

Ruby позволяет добавлять методы к любому конкретному экземпляру, делая это:

class << someinstance
  def foo
    "Hello."
  end
end

Это добавляет метод foo к некоторому состоянию, а не к его классу, а к одному конкретному экземпляру. (Фактически, foo добавляется в экземпляр "singleton class", но это более или менее причуда реализации.) После выполнения вышеуказанного кода вы можете отправить метод foo в someinstance:

someinstance.foo   => "Hello."

но вы не можете отправить foo в другие экземпляры одного и того же класса. То, для чего << номинально. Но люди чаще используют эту функцию для синтаксической гимнастики следующим образом:

class Thing
  def do_something
  end

  class << self
    def foo
      puts "I am #{self}"
    end
  end
end

Когда этот код - это определение класса - выполняется, что такое self? Это класс Thing. Это означает, что class << self совпадает с тем, что "добавьте следующие методы в класс Thing". То есть foo - метод класса. После того, как вы закончите, вы можете сделать это:

t = Thing.new
t.do_something  => does something
t.class.foo     => "I am Thing"
t.foo           => NoMethodError: undefined method `foo'

И когда вы думаете о том, что делает <<, все это имеет смысл. Это способ добавления к конкретному экземпляру, и в общем случае добавляемый экземпляр является классом, поэтому методы внутри блока становятся методами класса.

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

class Thing
  def self.foo
    # ...
  end
end

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

Ответ 3

Если вы хотите наследовать (в зависимости от названия вопроса), вам нужен один <:

class Awesome < ParentAwesomeness

Код, который вы указываете, недействителен ruby:

class Awesomeness
end

class Awesome << Awesomeness
end

SyntaxError: (irb):3: syntax error, unexpected tLSHFT, expecting '<' or ';' or '\n'