Разница между классом и модулем

Я пришел с Java, и теперь я больше работаю с Ruby.

одна особенность языка, с которой я не знаком, - это module. Мне интересно, что такое module и когда вы используете один, и зачем использовать module на class?

10 ответов


первый ответ хорош и дает некоторые структурные ответы, но другой подход-подумать о том, что вы делаете. Модули предоставляют методы, которые можно использовать в нескольких классах - подумайте о них как о "библиотеках" (как вы увидите в приложении 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)          ║
╚═══════════════╩═══════════════════════════╩═════════════════════════════════╝

Я удивлен, что никто еще не сказал этого.

поскольку asker пришел из Java-фона (и я тоже), вот аналогия, которая помогает.

классы просто похожи на классы Java.

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


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

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


(этот ответ первоначально связан с http://www.rubycentral.com/pickaxe/classes.html, но эта ссылка и ее домен больше не активны.)


Module в Ruby, в определенной степени, соответствует Java абстрактный класс -- есть методы экземпляра, классы могут наследовать от него (через include, Ruby guys называют это "mixin"), но не имеет экземпляров. Есть и другие незначительные различия, но этой информации достаточно, чтобы вы начали.


итог: модуль представляет собой нечто среднее между статическим / служебным классом и mixin.

Mixins-это многоразовые части "частичной" реализации, которые могут быть объединены (или составлены) способом mix & match, чтобы помочь написать новые классы. Эти классы могут дополнительно иметь свое собственное состояние и / или код, конечно.


источник (вы можете узнать характеристики модуля оттуда)

модуль представляет собой набор методов и констант. Методы в модуле могут быть методами экземпляра или методами модуля. Методы экземпляра отображаются как методы в классе, когда модуль включен, методы модуля-нет. И наоборот, методы модуля могут вызываться без создания инкапсулирующего объекта, а методы экземпляра-нет.


класс

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

модуль

  • модули-это способ группировки методов, классов и констант.

  • модули дают вам два основных преимущества:

    => модули предоставляют пространство имен и предотвращают имя столкновения. Пространство имен помогает избежать конфликтов с функциями и классами с тем же именем, которые были написаны кем-то другим.

    => модули реализуют объект mixin.

(включая модуль в Klazz дает экземплярам Klazz доступ к модулю методы. )

(расширение Klazz с модом, дающим классу Klazz доступ к методам модов.)


пространство имен: модули пространства имен...которые не существуют в Java ;)

Я также переключился с Java и python на Ruby, я помню, что у меня был точно такой же вопрос...

таким образом, самый простой ответ заключается в том, что модуль-это пространство имен, которое не существует в Java. В java ближайшим мышлением к пространству имен является пакета.

таким образом, модуль в ruby похож на то, что в java:
класса? нет
интерфейс? Нет!--14-->абстрактный класс? нет
пакета? да (может быть)

статические методы внутри классов в java: такие же, как методы внутри модулей в ruby

в java минимальная единица является классом, вы не можете иметь функцию вне класса. Однако в ruby это возможно (например, python).

Итак, что входит в модуль?
классы, методы, константы. Модуль защищает их под этим пространством имен.

нет пример: модули нельзя использовать для создания экземпляров

смешанные модули: иногда модели наследования не подходят для классов, но с точки зрения функциональности хотят сгруппировать набор классов/ методов/ констант вместе

правила о модулях в ruby:
- Имена модулей-UpperCamelCase
- константы внутри модулей-это все шапки (это правило одинаково для всех констант ruby, не специфичных для модулей)
- методы доступа: использование . оператор
- константы доступа: use:: symbol

простой пример модуля:

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)


во-первых, некоторые сходства, которые еще не были упомянуты. Ruby поддерживает открытые классы, но модули также открыты. В конце концов, класс наследует от 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 не унаследовал никаких методов от зеленого модуля, и когда мы включили Apple в класс фруктов, методы Модуль Apple добавляется в цепочку предков экземпляров Apple, но не методы зеленого модуля, хотя зеленый модуль был определен в модуле Apple.

Итак, как мы получаем доступ к зеленому методу? Вы должны явно включить его в свой класс:

class Fruit
  include Apple::Green
end
 => Fruit 
 > f.green
=> green

но Ruby имеет другое важное использование для модулей. Это объект Mixin, который я описываю в другом ответе на SO. Но подводя итог, mixins позволяют определить методы в наследование цепочка объектов. С помощью mixins можно добавить методы в цепочку наследования экземпляров объектов (include) или singleton_class self (extend).