Спадщина класу 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.