Я пытаюсь понять цель модуля Ruby с точки зрения дизайна.Может ли модуль Ruby описываться как одноэлементный класс?
Является ли модуль Ruby по существу просто классом, который инициализируется только один раз?
include MyModule
Я пытаюсь понять цель модуля Ruby с точки зрения дизайна.Может ли модуль Ruby описываться как одноэлементный класс?
Является ли модуль Ruby по существу просто классом, который инициализируется только один раз?
include MyModule
Класс рубин является модулем вы можете создавать экземпляры. Как класс, модуль может иметь методы, но вы не можете создать экземпляр модуля. Это единственное различие между ними.
На практике модули обычно используются для:
Вот пример модуля используется в качестве пространства имен:
module MyLib
class Foo
end
class Bar
end
end
Полное имя этих классов - MyLib :: Foo и MyLib :: Bar. Поскольку они содержатся в пространстве имен (который предположительно является уникальным), имена Foo и Bar не могут конфликтовать с Foo или Bar, определенными в вашей программе или в другой библиотеке.
Вот модуль, используемый в качестве смеси-в:
module Mixin
def foo
puts "foo"
end
end
Поскольку вы не можете сделать экземпляр подмешать модуля, вы получите доступ к обув путем включения (смешивание в) модуль:
class MyClass
include Mixin
end
MyClass.new.foo # => foo
Как класс, модуль может содержать функции й не работают ни в одном экземпляре. Для этого необходимо определить методы класса в модуле:
module SomeFunctions
def self.foo
puts "foo"
end
end
Метод класса определен в модуле только как методы класса, определенных в классе. Назовем его:
SomeFunctions.foo # => foo
Класс - это модуль, но модуль не является классом. Module
- это буквально суперкласс Class
. Если вы знаете ООП, это все, что вам нужно знать.
Рубиновые модули лучше всего использовать в качестве пространств имен и использоваться в миксинах.
Я сомневаюсь. В терминах Ruby модуль - это особый тип «класса», который не может быть создан. – Vineeth
Сделайте «Class.superclass» в irb, и он предоставит 'Module'. Однако выполнение 'Module.class' даст' Class'. т. е. 'Module' является экземпляром класса, а также является суперклассом. :) –
Модули имеют два вида использования в Ruby: namespacing констант и как mixins.
Пространства имен констант просто означает, что в
FOO = 1
module Bar
FOO = 2
end
module Baz
FOO = 3
end
есть три различных FOO
с в трех разных пространствах имен: один в глобальном пространстве имен (который на самом деле Object
), один в Bar
и один в Baz
.
Более интересным вариантом использования является mixins: mixin - это в основном класс, который параметризуется над его суперклассом. Или, говоря иначе: mixin - это класс, который может появляться несколько раз в графе наследования, каждый раз с другим суперклассом.
Контраста это множественное наследование: в множественном наследовании, класс может появиться только один раз в наследстве графа, но он может иметь несколько суперкласса. Миксин может отображаться несколько раз в графе наследования, но каждый случай имеет только один суперкласс.
В частности, то, что происходит в Ruby, когда вы смешиваете модуль M
в класс C
является то, что создана фактический класс (так называемый включают класс) (назовем его M′
), чей метод таблицы, константа и указатели таблицы переменных указывают на таблицу методов M
, таблицу констант и таблицу переменных, а этот класс M′
становится суперклассом C
со старым суперклассом, который становится суперклассом M′
.
Я согласен, но я думаю, что ваш третий вариант на самом деле просто извращенная альтернативная реализация вашего первого. Я не вижу причин, по которым вам когда-либо нужно было бы определить один метод на модуле, если, возможно, если вы также использовали его как mixin и хотели скрыть этот метод от экземпляров класса включения. – Borodin
Ваш третий пример - всего лишь пример одноэлементного класса. Он будет работать с любым объектом, а не только с модулем. –
@Borodin, Определение модуля функций является обычной практикой. Один хороший пример - в самой библиотеке Ruby: http://www.ruby-doc.org/core-2.0.0/Math.html –