En profundidad Ruby: Modules & Include vs. Extend

Ruby proporciona una construcción llamada Module que es como una Clase delgada. Al principio, los desarrolladores de Ruby pueden mirar Módulos como un «cajón de basura» de código que se lanza y se usa para organizar archivos, pero hay un método para esta locura. La clase Ruby Class hereda de Module y agrega cosas como instanciación, propiedades, etc., todas las cosas que normalmente pensarías que tendría una clase. Debido a que Module es literalmente un antepasado de Class, esto significa que los módulos pueden tratarse como clases de alguna manera.

Lo más importante para entender es cómo funciona la cadena de ancestros de Ruby. Como todos los lenguajes de programación orientada a objetos, Ruby admite la herencia. Cuando heredas de una clase, la superclase se agrega a tu cadena de ancestros. Usted puede ver los antepasados de cualquier clase llamando ancestors en él:

class Foo < BarendFoo.ancestors#=> 

Como se ha mencionado, usted puede encontrar Module en el array Class.ancestors.

Cuando include un módulo en su clase, el módulo se agrega a la cadena de ancestros de su clase, al igual que una clase. Esto hace que include sea solo una forma de herencia, no tiene nada de especial.

module Barendclass Foo include BarendFoo.ancestors#=> 

Todos los métodos en el Bar se agregan a Foo como métodos de instancia. Debido a que Bar está en la cadena, incluso puede llamar a super desde él para llamar a los métodos por encima de él en la cadena, ya sea que estén definidos en Módulos o Clases.

class Baz def hello p 'world' endendmodule Bar def hello p 'hello' super endendclass Foo < Baz include BarendFoo.new.hello#=> hello world

aunque Bar es un módulo, super llama a la cadena y así Baz#hello también es llamado. Vale la pena señalar que Bar se agrega a la cadena de ancestros delante de Baz. Cuando se incluye un módulo, siempre se agrega directamente encima de su clase de inclusión. Esto puede ser confuso al agregar varios módulos, ya que se incluyen en orden «inverso» :

class Foo include A include BendFoo.ancestors#=> 

Cuando A incluido, que se inserta directamente encima de Foo. Pero cuando se incluye B, también se inserta directamente encima de Foo, por lo que termina aterrizando antes de A.

include vs extend

include es bastante fácil de entender, agrega los métodos del módulo como métodos de instancia a su clase incluida. Puedes pensar en extend haciendo lo mismo, pero agregando los métodos como métodos de clase.

module Bar def hello p 'hello' endendclass Foo extend BarendFoo.hello # no .new!# => 'hello'

anteponer

además De incluir/ampliar, Ruby 2.0+ añade la etiqueta prepend método. prepend es similar a include, pero en su lugar inserta el módulo antes de la clase de inclusión en la cadena de herencia.

class Foo include Bar prepend BazendFoo.ancestors#=> 

En Ruby puede volver a abrir cualquier clase y redefinir los métodos en ella – no parece útil anular los métodos en una clase utilizando un módulo antepuesto en lugar de redefinirlos. Donde prepend es útil es cuando todavía necesita la implementación original del método, porque los módulos antepuestos pueden anular los métodos pero aún usan super para llamar a la implementación original.

Deja una respuesta

Tu dirección de correo electrónico no será publicada.