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 module
y cuándo usa uno, y por qué usar un module
sobre a class
?
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 module
y cuándo usa uno, y por qué usar un module
sobre a class
?
Respuestas:
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í).
╔═══════════════╦═══════════════════════════╦═════════════════════════════════╗
║ ║ 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) ║
╚═══════════════╩═══════════════════════════╩═════════════════════════════════╝
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 Math
clase en Java. No lo instancia, y reutiliza los métodos en la clase estática (por ejemplo Math.random()
).
extend self
), haciendo que sus métodos estén disponibles para su self
metaclase. Esto permite enviar un método como random()
en un Math
mó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.
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).
extend
una clase. Ruby en realidad no distingue entre los métodos de "instancia" y "clase / estática", solo los receptores de ellos.
Module
en 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.
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)
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.
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)
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).