«Нормальными» методами, определенными внутри блока class
, являются методы экземпляра :
class Foo
def bar
end
end
Методы, определенные в class << self
внутри блока class
: методы класса :
class Foo
class << self
def baz
end
end
end
Методы экземпляра становятся доступными для любого экземпляра данного класса:
foo = Foo.new
foo.bar
Принимая во внимание, что методы класса могут быть вызваны непосредственно в классе:
Foo.baz
Попытка вызова методов экземпляра в классе или наоборот приводит к ошибке:
Foo.bar #=> NoMethodError: undefined method `bar' for Foo:Class
foo.baz #=> NoMethodError: undefined method `baz' for #<Foo:0x00007ffe20055a20>
Еще один способ определения методов класса - префикс имени метода с self.
:
class Foo
def self.baz
end
end
Вы также можете определить их вне блока class
, хотя это редко можно увидеть:
def Foo.baz
end
Или также:
class << Foo
def baz
end
end
Обратите внимание, что определение методов таким способом не ограничивается классами. Вы можете добавлять методы к произвольным объектам, например ::
o = Object.new
def o.hello
"hello from o"
end
o.hello
#=> "hello from o"
Или через:
class << o
def hello
"hello from o"
end
end
Внутренне эти методы добавляются к одноэлементному классу объекта . Это специальный класс для хранения методов только для этого экземпляра:
o.singleton_class.instance_methods(false)
#=> [:hello]
Для Foo
класса выше:
Foo.instance_methods(false) #=> [:bar]
Foo.singleton_class.instance_methods(false) #=> [:baz]
Технически, метод класса - это просто метод экземпляра, определенный в синглтон-классе класса.