Спадщина класу Ruby: Що таке `<<` (вдвічі менше ніж)?


74
class << Awesomeness

Для чого це <<? Я шукав, але результати говорять мені лише про конкатенацію рядків ...

Відповіді:


135

Хоча це правда, що class << somethingце синтаксис для синглтон-класу, як сказав хтось інший, він найчастіше використовується для визначення методів класу в межах визначення класу. Але ці два звички узгоджуються. Ось як.

Ruby дозволяє додавати методи до будь-якого конкретного екземпляра, роблячи це:

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

Це додає метод fooдо деякої обставини, не до свого класу, а до того конкретного екземпляра. (Насправді, foo додається до "синглтон-класу" екземпляра ", але це більш-менш химерність реалізації.) Після виконання вищевказаного коду ви можете надіслати метод foo до деякої обставини:

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

Однакові речі. Ваш приклад насправді є синтаксичною помилкою, але якщо ви розумієте, як <<використовується з екземплярами та ключовим словом класу, ви будете знати, як це виправити.


1
Цікаво! Чи корисний такий метод у повсякденному програмуванні?
Волдеморт

6
@Omega: Так, ви побачили б це, наприклад, коли у вас є більше ніж один метод, який ви хочете зробити методом класу, і ви не хочете, щоб перед усіма ними ставився префікс "self". Ви можете просто помістити їх усіх у цей блок і не турбуватися про це.
solidcell

чудова робота - це демістифіковані інші відповіді, з якими я стикався.
Ларрі

Останній біт змусив це клацнути. Також зверніть увагу, що це class << selfпрацює в тому сенсі, що, хоч і Thingє класом, це також просто екземпляр його суперкласу. Тож у класах проти екземплярах немає нічого особливого. Кожен клас в ruby ​​є екземпляром свого суперкласу (за винятком BasicObject).
ahnbizcad

Дякую за пояснення, це було пояснено дуже добре.
піксель 67,

21

<<- це синтаксис для "визначення класу Singleton" . Ось приклад того, де / як він "типово" використовується.

У a = "abc"; a << "xyz"ньому є синтаксис "додавання даних" (до рядка, масиву тощо)


Він використовується таким чином, витягнутий із вкладеної форми gem : simple_form_for (* (args << options), & block) << after_nested_form_callbacks
shadowbq

8
У Ruby <<називаєтьсяshovel operator
піксель 67

20

Якщо ви хочете отримати спадщину (виходячи з назви вашого запитання), вам потрібен один <:

class Awesome < ParentAwesomeness

Введений вами код не є дійсним ruby:

class Awesomeness
end

class Awesome << Awesomeness
end

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

ВЕЛИКИЙ знати. Важко знайти цей фактоїд під час пошуку.
ahnbizcad

дивно, як мало хто дивився на заголовок. Інші пояснення чудові, але начебто пропустили те, що шукав запитувач.
ObjectNameDisplay
Використовуючи наш веб-сайт, ви визнаєте, що прочитали та зрозуміли наші Політику щодо файлів cookie та Політику конфіденційності.
Licensed under cc by-sa 3.0 with attribution required.