Recap: include e a cadeia de ancestrais

Prévia grátis 3 min de leitura

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

  • .ancestors devolve a lista ordenada que o Ruby percorre para achar um método.
  • include insere 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.
Aula 1 de 7 · grátis

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.

Digite para buscar...