Recap: include e a cadeia de ancestrais
Uma linha que você já escreveu, vista de perto
Em Módulos Ruby você escreveu include SomeModule dentro do corpo de uma classe para misturar os métodos de um módulo em toda instância da classe. Este curso não ensina isso de novo. Ele responde a uma pergunta mais precisa, que o curso anterior só tocou. Quando o Ruby procura um método, em que ordem ele olha os lugares onde o método pode estar?
module Startable
def start
"engine turns over"
end
end
class Car
include Startable
def start
"car starts smoothly"
end
end
Car inclui Startable e também define o próprio start. Uma chamada a Car.new.start roda só um desses dois corpos de método. Qual deles roda, e por quê, depende de um método que toda classe tem: .ancestors.
.ancestors: a ordem de busca
Car.ancestors
# [Car, Startable, Object, Kernel, BasicObject]
Esse array é a ordem que o Ruby percorre quando você chama um método numa instância de Car. O Ruby olha Car, depois Startable, depois Object, depois Kernel, depois BasicObject. Ele para no primeiro lugar que define o método chamado.
Car.new.start
# "car starts smoothly"
Car vem primeiro no array e define start, então a busca para ali. Startable#start existe e está na cadeia de ancestors, mas nunca roda. O método de Car vence porque o Ruby olha Car primeiro.
Quando a classe não define o método
class Motorcycle
include Startable
end
Motorcycle.new.start
# "engine turns over"
Motorcycle nunca define start. A busca começa em Motorcycle, passa pelos ancestors, chega a Startable e para ali. É o mesmo algoritmo com outro resultado, porque desta vez nada antes na cadeia atrapalhou.
O padrão até aqui
include insere um módulo logo depois da classe em .ancestors, e a regra é só essa. O método da própria classe fica antes do módulo na cadeia, então vence quando os dois definem o mesmo nome. O módulo só tem a vez quando a classe não define aquele método.
Esse fato, módulo depois da classe, vai ganhar uma contrapartida. O resto do curso trata de mais uma palavra-chave, que põe o módulo em outro lugar do mesmo array, e do que muda por causa disso.
Para onde o curso vai
São sete aulas. Esta relembra onde o include põe um módulo. Depois vêm o prepend e onde ele entra, os .ancestors dos dois lado a lado e um trace mostrando qual corpo de método roda primeiro. Em seguida: como o super se comporta dentro de um módulo com prepend, as duas palavras-chave numa classe só e uma aula final sobre como escolher. Cada afirmação é checada rodando código.
Pontos-chave
.ancestorsdevolve a lista ordenada que o Ruby percorre para achar um método.includeinsere um módulo logo depois da classe nessa lista:[Car, Startable, Object, Kernel, BasicObject].- Como a classe vem primeiro, o método dela vence o método de mesmo nome de um módulo incluído.
- Quando a classe não define o método, a busca continua pela cadeia e chega ao módulo.
Continue com a aula 2
prepend insere um module antes da classe
Mostra que prepend põe o módulo antes da classe, então o método dele roda primeiro e controla a chamada.
Com uma conta grátis você também tem os quizzes, seu progresso e suas anotações, e a discussão.