Ответы:
Первый ответ хорош и дает некоторые структурные ответы, но другой подход - подумать о том, что вы делаете. Модули предназначены для предоставления методов, которые вы можете использовать в нескольких классах - думайте о них как о «библиотеках» (как вы видели бы в приложении Rails). Классы об объектах; модули о функциях.
Например, системы аутентификации и авторизации являются хорошими примерами модулей. Системы аутентификации работают в нескольких классах уровня приложения (пользователи проходят аутентификацию, сеансы управляют аутентификацией, многие другие классы будут работать по-разному в зависимости от состояния аутентификации), поэтому системы аутентификации действуют как общие API.
Вы также можете использовать модуль, когда у вас есть общие методы для нескольких приложений (опять же, модель библиотеки здесь хорошая).
╔═══════════════╦═══════════════════════════╦═════════════════════════════════╗
║ ║ class ║ module ║
╠═══════════════╬═══════════════════════════╬═════════════════════════════════╣
║ instantiation ║ can be instantiated ║ can *not* be instantiated ║
╟───────────────╫───────────────────────────╫─────────────────────────────────╢
║ usage ║ object creation ║ mixin facility. provide ║
║ ║ ║ a namespace. ║
╟───────────────╫───────────────────────────╫─────────────────────────────────╢
║ superclass ║ module ║ object ║
╟───────────────╫───────────────────────────╫─────────────────────────────────╢
║ methods ║ class methods and ║ module methods and ║
║ ║ instance methods ║ instance methods ║
╟───────────────╫───────────────────────────╫─────────────────────────────────╢
║ inheritance ║ inherits behaviour and can║ No inheritance ║
║ ║ be base for inheritance ║ ║
╟───────────────╫───────────────────────────╫─────────────────────────────────╢
║ inclusion ║ cannot be included ║ can be included in classes and ║
║ ║ ║ modules by using the include ║
║ ║ ║ command (includes all ║
║ ║ ║ instance methods as instance ║
║ ║ ║ methods in a class/module) ║
╟───────────────╫───────────────────────────╫─────────────────────────────────╢
║ extension ║ can not extend with ║ module can extend instance by ║
║ ║ extend command ║ using extend command (extends ║
║ ║ (only with inheritance) ║ given instance with singleton ║
║ ║ ║ methods from module) ║
╚═══════════════╩═══════════════════════════╩═════════════════════════════════╝
Я удивлен, что никто еще не сказал это.
Поскольку спрашивающий пришел из Java-фона (и я тоже), вот аналогия, которая помогает.
Классы просто похожи на классы Java.
Модули похожи на статические классы Java. Подумайте о Math
классе в Java. Вы не создаете его экземпляр и повторно используете методы в статическом классе (например, Math.random()
).
extend self
), делая их методы доступными для их self
метакласса. Это позволяет отправлять метод как random()
в Math
модуле. Но по своей природе методы модуля не могут быть вызваны самим модулем self
. Это связано с понятием Руби self
, его метаклассами и тем, как работает поиск методов. Проверьте "Метапрограммирование Руби" - Паоло Перлотта для деталей.
По сути, модуль не может быть создан. Когда класс включает в себя модуль, создается прокси-суперкласс, который обеспечивает доступ ко всем методам модуля, а также к методам класса.
Модуль может быть включен несколькими классами. Модули не могут быть унаследованы, но эта модель "mixin" предоставляет полезный тип "множественного наследования". ОО-пуристы не согласятся с этим утверждением, но не позволяют чистоте мешать выполнению работы.
(Этот ответ изначально связан с http://www.rubycentral.com/pickaxe/classes.html
, но эта ссылка и ее домен больше не активны.)
extend
используя класс. На самом деле Ruby вообще не различает методы «instance» и «class / static», только их получатели.
Module
в Ruby, в некоторой степени, соответствует абстрактному классу Java - имеет методы экземпляра, классы могут наследовать от него (через include
, ребята из Ruby называют его «mixin»), но не имеют экземпляров. Существуют и другие незначительные различия, но этого достаточно, чтобы начать работу.
namespace: модули - это пространства имен ... которые не существуют в java;)
Я также переключился с Java и Python на Ruby, я помню, был точно такой же вопрос ...
Таким образом, самый простой ответ заключается в том, что модуль является пространством имен, которого нет в Java. В Java самый близкий образ мышления к пространству имен - это пакет .
Таким образом, модуль в ruby похож на то, что в java:
class? Нет
интерфейса? Нет
абстрактного класса? Нет
пакета? Да, может быть)
статические методы внутри классов в java: так же, как методы внутри модулей в ruby
В Java минимальной единицей является класс, у вас не может быть функции вне класса. Однако в ruby это возможно (как в python).
Итак, что входит в модуль?
классы, методы, константы. Модуль защищает их в этом пространстве имен.
Нет экземпляра: модули не могут быть использованы для создания экземпляров
Смешанные модули: иногда модели наследования не подходят для классов, но с точки зрения функциональности хотят сгруппировать набор классов / методов / констант вместе
Правила для модулей в ruby:
- Имена модулей - UpperCamelCase
- константы внутри модулей - ВСЕ CAPS (это правило одинаково для всех констант ruby, не специфично для модулей)
- методы доступа: использовать. оператор
- константы доступа: используйте :: символ
Простой пример модуля:
module MySampleModule
CONST1 = "some constant"
def self.method_one(arg1)
arg1 + 2
end
end
как использовать методы внутри модуля:
puts MySampleModule.method_one(1) # prints: 3
Как использовать константы модуля:
puts MySampleModule::CONST1 # prints: some constant
Некоторые другие соглашения о модулях:
Используйте один модуль в файле (например, классы ruby, один класс на файл ruby)
Итог: модуль представляет собой нечто среднее между статическим / служебным классом и миксином.
Миксины - это многократно используемые части «частичной» реализации, которые можно комбинировать (или составлять) в режиме «смешивать и сочетать», чтобы помочь в написании новых классов. Конечно, эти классы могут иметь собственное состояние и / или код.
Учебный класс
Когда вы определяете класс, вы определяете план для типа данных. класс содержит данные, имеет метод, который взаимодействует с этими данными и используется для создания экземпляров объектов.
модуль
Модули - это способ группировки методов, классов и констант.
Модули дают вам два основных преимущества:
=> Модули предоставляют пространство имен и предотвращают конфликты имен. Пространство имен помогает избежать конфликтов с функциями и классами с тем же именем, которые были написаны кем-то другим.
=> Модули реализуют смешанный механизм.
(Включение модуля в Klazz дает экземплярам доступа Klazz к методам модуля.)
(расширить Klazz с помощью Mod, предоставив классу Klazz доступ к методам Mods.)
Во-первых, некоторые сходства, которые еще не были упомянуты. Ruby поддерживает открытые классы, но модули также открыты. В конце концов, Class наследует от Module в цепочке наследования Class, и поэтому Class и Module имеют похожее поведение.
Но вы должны спросить себя, какова цель наличия класса и модуля на языке программирования? Предполагается, что класс является планом для создания экземпляров, а каждый экземпляр представляет собой реализованный вариант плана. Экземпляр - это просто реализованная вариация проекта (Класса). Естественно, что классы функционируют как создание объектов. Кроме того, поскольку иногда мы хотим, чтобы один проект был получен из другого проекта, классы предназначены для поддержки наследования.
Модули не могут быть созданы, не создают объекты и не поддерживают наследование. Помните, что один модуль НЕ наследуется от другого!
Так в чем же смысл наличия модулей на языке? Одно из очевидных применений модулей - создание пространства имен, и вы заметите это и на других языках. Опять же, что хорошо в Ruby, так это то, что Модули можно открывать снова (так же, как Классы). И это большое использование, когда вы хотите повторно использовать пространство имен в разных файлах Ruby:
module Apple
def a
puts 'a'
end
end
module Apple
def b
puts 'b'
end
end
class Fruit
include Apple
end
> f = Fruit.new
=> #<Fruit:0x007fe90c527c98>
> f.a
=> a
> f.b
=> b
Но нет наследования между модулями:
module Apple
module Green
def green
puts 'green'
end
end
end
class Fruit
include Apple
end
> f = Fruit.new
=> #<Fruit:0x007fe90c462420>
> f.green
NoMethodError: undefined method `green' for #<Fruit:0x007fe90c462420>
Модуль Apple не наследовал никаких методов от модуля Green, и когда мы включили Apple в класс Fruit, методы модуля Apple были добавлены в цепочку предков экземпляров Apple, но не в методы модуля Green, хотя Green модуль был определен в модуле Apple.
Так как же нам получить доступ к зеленому методу? Вы должны явно включить его в свой класс:
class Fruit
include Apple::Green
end
=> Fruit
> f.green
=> green
Но у Ruby есть еще одно важное применение для модулей. Это средство Mixin, которое я опишу в другом ответе на SO. Подводя итог, можно сказать, что миксины позволяют определять методы в цепочке наследования объектов. С помощью миксинов вы можете добавлять методы в цепочку наследования экземпляров объектов (include) или singleton_class класса self (extension).