_If you wish to report errors or suggest improvements for this FAQ,
please go to our
[GitHub repository](https://github.com/ruby/www.ruby-lang.org/)
and open an issue or pull request._


## Классы и модули

### Может ли определение класса повторяться?

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

### Существуют ли переменные класса?

Да. Переменная с префиксом из двух символов «собака» (`@@`) — это переменная класса, доступная как в методах экземпляра, так и в методах класса.

~~~
class Entity

  @@instances = 0

  def initialize
    @@instances += 1
    @number = @@instances
  end

  def who_am_i
   "I'm #{@number} of #{@@instances}"
  end

  def self.total
    @@instances
  end
end

entities = Array.new(9) { Entity.new }

entities[6].who_am_i  # => "I'm 7 of 9"
Entity.total          # => 9
~~~

Однако вам, вероятно, стоит использовать _переменные экземпляра класса_ (class instance variables) вместо них.

### Что такое переменная экземпляра класса?

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

~~~
class Entity

  @instances = 0

  class << self
    attr_accessor :instances  # provide class methods for reading/writing
  end

  def initialize
    self.class.instances += 1
    @number = self.class.instances
  end

  def who_am_i
   "I'm #{@number} of #{self.class.instances}"
  end

  def self.total
    @instances
  end
end

entities = Array.new(9) { Entity.new }

entities[6].who_am_i  # => "I'm 7 of 9"
Entity.instances      # => 9
Entity.total          # => 9
~~~

Здесь `@instances` — это переменная экземпляра _класса_. Она принадлежит не экземпляру класса `Entity`, а самому объекту класса `Entity`, который является экземпляром класса `Class`.

Переменные экземпляра класса доступны напрямую только внутри методов класса.

### В чем разница между переменными класса и переменными экземпляра класса?

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

Переменные класса в некотором роде можно рассматривать как глобальные переменные в контексте иерархии наследования со всеми вытекающими проблемами. Например, переменная класса может быть (случайно) переприсвоена любым из подклассов, что повлияет на все остальные классы:

~~~
class Woof

  @@sound = "woof"

  def self.sound
    @@sound
  end
end

Woof.sound  # => "woof"

class LoudWoof < Woof
  @@sound = "WOOF"
end

LoudWoof.sound  # => "WOOF"
Woof.sound      # => "WOOF" (!)
~~~

Или класс-предок может быть позже открыт заново и изменен, что приведет к неожиданным эффектам:

~~~
class Foo

  @@var = "foo"

  def self.var
    @@var
  end
end

Foo.var  # => "foo" (as expected)

class Object
  @@var = "object"
end

Foo.var  # => "object" (!)
~~~

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

### Есть ли в Ruby методы класса?
{: #class-method}

[Синглтон-метод](../7/#singleton-method) объекта класса называется методом класса. (На самом деле метод класса определяется в метаклассе, но это происходит практически незаметно). Другой способ взглянуть на это — сказать, что метод класса — это метод, получателем которого является класс.

Все сводится к тому, что вы можете вызывать методы класса, не имея экземпляров этого класса (объектов) в качестве получателя.

Давайте создадим синглтон-метод класса `Foo`:

~~~
class Foo
  def self.test
    "this is foo"
  end
end

# It is invoked this way.

Foo.test  # => "this is foo"
~~~

В этом примере `Foo.test` является методом класса.

Методы экземпляра, определенные в классе `Class`, могут использоваться как методы класса для каждого(!) класса.

### Что такое синглтон-класс?

Синглтон-класс (singleton class) — это анонимный класс, который создается путем наследования класса, связанного с конкретным объектом. Синглтон-классы — это еще один способ расширения функциональности только одного объекта.

Возьмем скромный `Foo`:

~~~
class Foo
  def hello
    "hello"
  end
end

foo = Foo.new
foo.hello  # => "hello"
~~~

Теперь допустим, нам нужно добавить функциональность на уровне класса только для этого одного экземпляра:

~~~
class << foo
  attr_accessor :name

  def hello
    "hello, I'm #{name}"
  end
end

foo.name = "Tom"
foo.hello         # => "hello, I'm Tom"
Foo.new.hello     # => "hello"
~~~

Мы настроили `foo` без изменения характеристик `Foo`.

### Что такое функция модуля?

<div class="not-prose bg-ruby-100 dark:bg-ruby-800 rounded-lg p-8 my-6">
  <div class="flex items-start gap-3">
    <svg class="w-6 h-6 text-ruby-700 dark:text-ruby-200 flex-shrink-0 mt-0.5" fill="currentColor" viewBox="0 0 20 20">
      <path fill-rule="evenodd" d="M8.485 2.495c.673-1.167 2.357-1.167 3.03 0l6.28 10.875c.673 1.167-.17 2.625-1.516 2.625H3.72c-1.347 0-2.189-1.458-1.515-2.625L8.485 2.495zM10 5a.75.75 0 01.75.75v3.5a.75.75 0 01-1.5 0v-3.5A.75.75 0 0110 5zm0 9a1 1 0 100-2 1 1 0 000 2z" clip-rule="evenodd"/>
    </svg>
    <p class="text-sm text-ruby-700 dark:text-ruby-200 italic">
      This section or parts of it might be out-dated or in need of confirmation.
    </p>
  </div>
</div>


Функция модуля — это приватный синглтон-метод, определенный в модуле. По сути, она похожа на [метод класса](#class-method) тем, что её можно вызвать с использованием нотации `Module.method`:

~~~
Math.sqrt(2)  # => 1.414213562
~~~

Однако, поскольку модули могут быть подмешаны в классы, функции модуля также могут использоваться без префикса (именно так все функции `Kernel` становятся доступными объектам):

~~~
include Math
sqrt(2)  # => 1.414213562
~~~

Используйте `module_function`, чтобы сделать метод функцией модуля.

~~~
module Test
  def thing
    # ...
  end
  module_function :thing
end
~~~

### В чем разница между классом и модулем?

Модули — это коллекции методов и констант. Они не могут создавать экземпляры. Классы могут создавать экземпляры (объекты) и имеют состояние для каждого экземпляра (переменные экземпляра).

Модули могут быть подмешаны (mixed in) в классы и другие модули. Константы и методы подмешанного модуля смешиваются с собственными константами и методами класса, дополняя его функциональность. Однако классы нельзя подмешить во что-либо.

Класс может наследоваться от другого класса, но не от модуля.

Модуль не может наследоваться ни от чего.

### Можно ли создавать подклассы модулей?

Нет. Однако модуль может быть включен в класс или другой модуль, чтобы имитировать множественное наследование (механизм примесей).

Это не создает подкласс (для чего потребовалось бы наследование), но создает отношение `is_a?` между классом и модулем.

### Дайте мне пример примеси (mixin)

Модуль `Comparable` предоставляет различные операторы сравнения (`<`, `<=`, `==`, `>=`, `>`, `between?`). Он определяет их через вызовы общего метода сравнения `<=>`. Однако сам он не определяет `<=>`.

Допустим, вы хотите создать класс, в котором сравнение основано на количестве ног у животного:

~~~
class Animal
  include Comparable

  attr_reader :legs

  def initialize(name, legs)
    @name, @legs = name, legs
  end

  def <=>(other)
    legs <=> other.legs
  end

  def inspect
    @name
  end
end

c = Animal.new("cat", 4)
s = Animal.new("snake", 0)
p = Animal.new("parrot", 2)

c < s             # => false
s < c             # => true
p >= s            # => true
p.between?(s, c)  # => true
[p, s, c].sort    # => [snake, parrot, cat]
~~~

Все, что должен сделать `Animal`, — это определить собственную семантику для оператора `<=>` и подмешить модуль `Comparable`. Методы `Comparable` теперь становятся неотличимы от методов `Animal`, и ваш класс внезапно обретает новую функциональность. А поскольку один и тот же модуль `Comparable` используется многими классами, ваш новый класс будет иметь согласованную и понятную семантику.

### Почему существует два способа определения методов класса?

Вы можете определить метод класса внутри определения класса или на верхнем уровне.

~~~
class Demo
  def self.class_method
  end
end

def Demo.another_class_method
end
~~~

Между ними есть только одно существенное различие. В определении класса вы можете обращаться к константам класса напрямую, так как они находятся в области видимости. На верхнем уровне вам придется использовать нотацию `Class::CONST`.

### В чем разница между `include` и `extend`?

<div class="not-prose bg-ruby-100 dark:bg-ruby-800 rounded-lg p-8 my-6">
  <div class="flex items-start gap-3">
    <svg class="w-6 h-6 text-ruby-700 dark:text-ruby-200 flex-shrink-0 mt-0.5" fill="currentColor" viewBox="0 0 20 20">
      <path fill-rule="evenodd" d="M8.485 2.495c.673-1.167 2.357-1.167 3.03 0l6.28 10.875c.673 1.167-.17 2.625-1.516 2.625H3.72c-1.347 0-2.189-1.458-1.515-2.625L8.485 2.495zM10 5a.75.75 0 01.75.75v3.5a.75.75 0 01-1.5 0v-3.5A.75.75 0 0110 5zm0 9a1 1 0 100-2 1 1 0 000 2z" clip-rule="evenodd"/>
    </svg>
    <p class="text-sm text-ruby-700 dark:text-ruby-200 italic">
      This section or parts of it might be out-dated or in need of confirmation.
    </p>
  </div>
</div>


`include` подмешивает модуль в класс или другой модуль. Методы из этого модуля вызываются в стиле функций (без получателя).

`extend` используется для включения модуля в объект (экземпляр). Методы модуля становятся методами объекта.

### Что означает `self`?

`self` — это текущий исполняемый получатель, объект, к которому применяется метод. Вызов метода в стиле функции подразумевает `self` в качестве получателя.
