In-Depth Ruby: Modules & Include vs. Extend

Ruby provides a construct called a Module which is sort of like a thin Class. No início, Ruby devs pode olhar para módulos como uma “gaveta de lixo” de código que é apenas jogado em torno e usado para organizar arquivos, mas há um método para esta loucura. A classe Ruby Class herda de Module e adiciona coisas como instanciação, propriedades, etc. – todas as coisas que você normalmente teria de pensar uma classe teria. Porque Module é, literalmente, um ancestral de Class, isto significa que os Módulos podem ser tratados como classes em alguns aspectos.

o mais importante para entender é como a cadeia ancestral Ruby funciona. Como todas as línguas OOP, Ruby suporta herança. Quando você herda de uma classe, a superclasse é adicionada à sua cadeia ancestral. Você pode exibir os antepassados de qualquer classe, chamando ancestors em que:

class Foo < BarendFoo.ancestors#=> 

Como mencionado, você pode encontrar Module na matriz Class.ancestors.

Quando você include um módulo em sua classe, o módulo é adicionado à cadeia ancestral da sua classe – assim como uma classe. Isto faz com que include apenas uma forma de herança, não há nada de especial sobre ele.

module Barendclass Foo include BarendFoo.ancestors#=> 

Todos os métodos de Bar são adicionados Foo como métodos de instância. Como a barra está na cadeia, você pode até mesmo chamar super a partir dela para chamar métodos acima dela na cadeia, se eles são definidos em módulos ou Classes.

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

Mesmo que Bar é um módulo, super ainda chama até a cadeia e, portanto, Baz#hello também é chamado. Vale a pena notar que Bar é adicionado à cadeia ancestral na frente de Baz. Quando um módulo é incluído, ele é sempre adicionado diretamente em cima dele está incluindo Classe. Isto pode ficar confuso ao adicionar vários módulos, uma vez que eles estão incluídos na ordem “reversa” :

class Foo include A include BendFoo.ancestors#=> 

Quando A é incluído, ele é inserido diretamente acima de Foo. Mas quando B está incluído, também é inserido diretamente acima de Foo, de modo que ele acaba de destino antes de A.

include vs extend

include is easy enough to understand, it adds the module’s methods as instance methods to it’s including class. Você pode pensar em extend fazendo a mesma coisa, mas em vez disso adicionando os métodos como métodos de classe.

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

prepend

In addition to include/extend, Ruby 2.0+ adds theprepend method. prependé semelhante ainclude, mas em vez disso insere o módulo antes da classe including na cadeia hereditária.

class Foo include Bar prepend BazendFoo.ancestors#=> 

Em Ruby você pode re-abrir qualquer classe e redefinir os métodos – não parece útil para substituir os métodos em uma classe usando um módulo anexado como oposição a redefinindo-os. Onde prepend vem a calhar é quando você ainda terá a implementação original do método, porque precedido de módulos que podem substituir os métodos, mas ainda usar super para chamar a implementação original.

Deixe uma resposta

O seu endereço de email não será publicado.