Diferencia entre una clase y un módulo.

438

Vengo de Java, y ahora estoy trabajando más con Ruby.

Una característica del idioma con la que no estoy familiarizado es module. Me pregunto qué es exactamente un moduley cuándo usa uno, y por qué usar un modulesobre a class?

Josh Moore
fuente

Respuestas:

398

La primera respuesta es buena y ofrece algunas respuestas estructurales, pero otro enfoque es pensar en lo que está haciendo. Los módulos consisten en proporcionar métodos que puede usar en varias clases; piense en ellos como "bibliotecas" (como vería en una aplicación Rails). Las clases son sobre objetos; Los módulos son sobre funciones.

Por ejemplo, los sistemas de autenticación y autorización son buenos ejemplos de módulos. Los sistemas de autenticación funcionan en varias clases de nivel de aplicación (los usuarios se autentican, las sesiones administran la autenticación, muchas otras clases actuarán de manera diferente según el estado de autenticación), por lo que los sistemas de autenticación actúan como API compartidas.

También puede usar un módulo cuando ha compartido métodos entre múltiples aplicaciones (nuevamente, el modelo de biblioteca es bueno aquí).

scottru
fuente
77
¿El módulo es el mismo que Interfaces en java?
Saad Rehman Shah
14
@Caffeine no realmente porque los módulos Ruby realmente incluyen implementaciones, mientras que las interfaces en Java son abstractas
Jorge Israel Peña
8
No, los módulos y los paquetes / JAR de Java son bestias completamente diferentes.
Karoly Horvath
99
Me gustan más las clases abstractas con la implementación de métodos.
Automatico
2
En realidad, @Chole se topa con una de las cosas buenas de los módulos: el espacio de nombres. Entonces, si bien los módulos no son un equivalente directo de los paquetes en Java, se pueden usar para lograr algo similar: blog.rubybestpractices.com/posts/gregory/…
michaelok
513
╔═══════════════╦═══════════════════════════╦═════════════════════════════════╗
║               ║ 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)          ║
╚═══════════════╩═══════════════════════════╩═════════════════════════════════╝
Sergii Shevchyk
fuente
¿Cuál es la superclase de la clase 'Clase'?
Aashish P
10
Obtuve la jerarquía, Clase -> Módulo -> Objeto -> Objeto básico. ¡¡Frio!!
Aashish P
¿Por qué "módulo consiste en" omitir variables, cuando las clases y los módulos admiten variables de clase? Vea la respuesta aceptada a stackoverflow.com/questions/5690458/…
kaleidic
Muchos diagramas en todas estas respuestas. Un pequeño ejemplo: rubyfiddle.com/riddles/06081
Donato
16
¿Cómo puede un módulo "no ser instanciado" y aún tener métodos de instancia?
devius
91

Me sorprende que nadie haya dicho esto todavía.

Dado que el autor de la pregunta proviene de un fondo de Java (y yo también), aquí hay una analogía que ayuda.

Las clases son simplemente como las clases de Java.

Los módulos son como las clases estáticas de Java. Piensa en la Mathclase en Java. No lo instancia, y reutiliza los métodos en la clase estática (por ejemplo Math.random()).

Linan
fuente
11
Pero los módulos también pueden agregar métodos de instancia a la clase incluida, mientras que las clases estáticas en Java no pueden.
Restablece a Monica - notmaynard el
44
Esta afirmación también es cierta proveniente de un fondo pesado de C #.
Damon Drake
55
Esto no es del todo cierto; los módulos no tienen métodos estáticos, solo tienen métodos. Los módulos pueden "extenderse" (la sintaxis es en realidad extend self), haciendo que sus métodos estén disponibles para su selfmetaclase. Esto permite enviar un método como random()en un Mathmódulo. Pero por su naturaleza, los métodos de un módulo no se pueden invocar por sí mismos self. Esto tiene que ver con la noción de Ruby self, sus metaclases y cómo funciona la búsqueda de métodos. Mira "Metaprogramming Ruby" - Paolo Perlotta para más detalles.
scottburton11
Diría que los módulos son más similares a las interfaces con métodos en ellos (interfaces Java 8 con impl implícito) pero no pueden heredar uno de otro a diferencia de las interfaces java
divideByZero
¿Cómo esta respuesta tiene tantos votos? por cierto que se dijo en mejores palabras 1mo antes: stackoverflow.com/a/17027346/986862
Andre Figueiredo
39

Básicamente, el módulo no puede ser instanciado. Cuando una clase incluye un módulo, se genera una superclase de proxy que proporciona acceso a todos los métodos del módulo, así como a los métodos de la clase.

Un módulo puede ser incluido por múltiples clases. Los módulos no se pueden heredar, pero este modelo "mixin" proporciona un tipo útil de "herencia múltiple". OO puristas no estarán de acuerdo con esa declaración, pero no dejes que la pureza se interponga en el camino para hacer el trabajo.


(Esta respuesta originalmente estaba vinculada a http://www.rubycentral.com/pickaxe/classes.html, pero ese enlace y su dominio ya no están activos).

huracán
fuente
Sí, así es como funciona. Como tal, los módulos no son comparables a las clases "estáticas" de Java; la superclase de proxy (algunos lo llaman "metaclase") se convierte en el receptor de los mensajes de envío de métodos del módulo, lo que lo hace más comparable a una clase estática en Java, y sus métodos funcionan como métodos estáticos. Sin embargo, lo mismo es cierto para las clases de Ruby, que pueden adoptar métodos "estáticos" al formar extenduna clase. Ruby en realidad no distingue entre los métodos de "instancia" y "clase / estática", solo los receptores de ellos.
scottburton11
7

Moduleen Ruby, hasta cierto punto, corresponde a la clase abstracta de Java : tiene métodos de instancia, las clases pueden heredar de ella (a través de include, los chicos de Ruby lo llaman "mixin"), pero no tiene instancias. Existen otras diferencias menores, pero esta cantidad de información es suficiente para comenzar.

Boris Stitnicky
fuente
6

espacio de nombres: los módulos son espacios de nombres ... que no existen en java;)

También cambié de Java y Python a Ruby, recuerdo que tenía exactamente esta misma pregunta ...

Entonces, la respuesta más simple es que el módulo es un espacio de nombres, que no existe en Java. En java, la mentalidad más cercana al espacio de nombres es un paquete .

Entonces, ¿un módulo en ruby ​​es como en java:
class? ¿Sin
interfaz? ¿No hay
clase abstracta? Sin
paquete?Si quizas)

métodos estáticos dentro de clases en java: igual que los métodos dentro de módulos en ruby

En java, la unidad mínima es una clase, no puede tener una función fuera de una clase. Sin embargo, en ruby ​​esto es posible (como python).

Entonces, ¿qué hay en un módulo?
clases, métodos, constantes. El módulo los protege bajo ese espacio de nombres.

Ninguna instancia: módulos no se pueden usar para crear instancias

Ins mixtos: veces los modelos de herencia no son buenos para las clases, pero en términos de funcionalidad quieren agrupar un conjunto de clases / métodos / constantes

Reglas sobre módulos en ruby:
- Los nombres de los módulos son UpperCamelCase
- las constantes dentro de los módulos son TODAS MAYÚSCULAS (esta regla es la misma para todas las constantes ruby, no específicas de los módulos)
- métodos de acceso: uso. operador
- constantes de acceso: uso :: símbolo

ejemplo simple de un módulo:

module MySampleModule
  CONST1 = "some constant"

  def self.method_one(arg1)
    arg1 + 2
  end
end

Cómo usar métodos dentro de un módulo:

puts MySampleModule.method_one(1) # prints: 3

Cómo usar las constantes de un módulo:

puts MySampleModule::CONST1 # prints: some constant

Algunas otras convenciones sobre módulos:
use un módulo en un archivo (como clases de ruby, una clase por archivo de ruby)

apadana
fuente
"- métodos de acceso: uso. operador - constantes de acceso: use :: symbol ”¡solo esta respuesta menciona esto!
Qiulang
4

En pocas palabras: un módulo es un cruce entre una clase estática / de utilidad y un mixin.

Los mixins son piezas reutilizables de implementación "parcial", que se pueden combinar (o componer) en una combinación y combinación, para ayudar a escribir nuevas clases. Estas clases también pueden tener su propio estado y / o código, por supuesto.

IQ Sayed
fuente
1

Clase

Cuando define una clase, define un plano para un tipo de datos. datos de retención de clase, tienen un método que interactúa con esos datos y se utilizan para crear instancias de objetos.

Módulo

  • Los módulos son una forma de agrupar métodos, clases y constantes.

  • Los módulos le brindan dos beneficios principales:

    => Los módulos proporcionan un espacio de nombres y evitan conflictos de nombres. El espacio de nombres ayuda a evitar conflictos con funciones y clases con el mismo nombre que han sido escritas por otra persona.

    => Los módulos implementan la instalación mixin.

(incluido el Módulo en Klazz proporciona instancias de acceso de Klazz a los métodos del Módulo).

(Extienda Klazz con Mod dando a la clase Klazz acceso a métodos Mods)

prasanthrubyist
fuente
0

Primero, algunas similitudes que aún no se han mencionado. Ruby admite clases abiertas, pero también módulos abiertos. Después de todo, Class hereda del Módulo en la cadena de herencia de Class y, por lo tanto, Class y Module tienen un comportamiento similar.

Pero debe preguntarse cuál es el propósito de tener una Clase y un Módulo en un lenguaje de programación. Se pretende que una clase sea un modelo para crear instancias, y cada instancia es una variación realizada del modelo. Una instancia es solo una variación realizada de un plano (la Clase). Entonces, naturalmente, las clases funcionan como creación de objetos. Además, dado que a veces queremos que un plano se derive de otro plano, las clases están diseñadas para admitir la herencia.

Los módulos no se pueden crear instancias, no crean objetos y no admiten herencia. ¡Recuerde que un módulo NO hereda de otro!

Entonces, ¿cuál es el punto de tener módulos en un idioma? Un uso obvio de los módulos es crear un espacio de nombres, y también lo notará con otros idiomas. Una vez más, lo bueno de Ruby es que los módulos se pueden volver a abrir (al igual que las clases). Y este es un gran uso cuando desea reutilizar un espacio de nombres en diferentes archivos 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

Pero no hay herencia entre los módulos:

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>

El módulo Apple no heredó ningún método del módulo Verde y cuando incluimos a Apple en la clase Fruit, los métodos del módulo Apple se agregan a la cadena de antecesores de las instancias de Apple, pero no los métodos del módulo Verde, a pesar de que el Verde El módulo se definió en el módulo de Apple.

Entonces, ¿cómo podemos acceder al método verde? Tienes que incluirlo explícitamente en tu clase:

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

Pero Ruby tiene otro uso importante para los módulos. Esta es la instalación de Mixin, que describo en otra respuesta sobre SO. Pero para resumir, los mixins le permiten definir métodos en la cadena de herencia de los objetos. A través de mixins, puede agregar métodos a la cadena de herencia de instancias de objeto (incluir) o singleton_class of self (extender).

Donato
fuente