LaunchKit
All quizzes
Ruby 0 views

alias vs alias_method across inheritance

Question

What is the return value of the following Ruby code?

class Device
  def description
    'I\'m a device'
  end

  def self.alias_description
    alias describe description
  end
end

class Microwave < Device
  def description
    'I\'m a microwave'
  end

  alias_description
end

m = Microwave.new
p m.description # => "I'm a microwave"

p m.describe # => ???

The correct answer is

Explanation

TL;DR

The alias keyword is resolved in the lexical scope where it is written. It sits inside a method defined in Device, so it aliases Device#description, even though the call that triggers it comes from Microwave's class body. m.describe returns "I'm a device", while the overriding m.description returns "I'm a microwave".

The alias keyword

class Device
  def description
    "I'm a device"
  end

  def self.alias_description
    alias describe description
  end
end

class Microwave < Device
  def description
    "I'm a microwave"
  end

  alias_description
end

m = Microwave.new

m.description # => "I'm a microwave"
m.describe    # => "I'm a device"

Microwave.instance_method(:describe).owner # => Device

alias is a keyword, not a method call. It is resolved against the class that lexically encloses the def it appears in, here Device. So when Microwave calls alias_description, the alias is installed on Device and copies Device#description. The owner check confirms it: describe lives on Device, and Microwave's override of description is never consulted.

An alias also captures the method definition current at the moment it runs: redefining description afterwards does not change what describe returns.

Module#alias_method

alias_method is a regular method call, so it operates on whatever self is at runtime. When alias_description is invoked from Microwave's class body, self is Microwave: the alias is defined on Microwave and method lookup finds the most specific description, the one defined in Microwave:

class Device
  def description
    "I'm a device"
  end

  def self.alias_description
    alias_method :describe, :description
  end
end

class Microwave < Device
  def description
    "I'm a microwave"
  end

  alias_description
end

m = Microwave.new

m.description # => "I'm a microwave"
m.describe    # => "I'm a microwave"

Microwave.instance_method(:describe).owner # => Microwave

The rule of thumb: alias follows the lexical scope, alias_method follows self. When writing code meant to be called from subclasses, alias_method usually does what you expect.

Share this quiz

Comments

No comments yet. Be the first.

Only used to confirm and publish your comment. Never shown publicly, never shared.

Markdown: **bold**, `code`, ```fenced blocks```, > quotes, [links](url). HTML and images are not rendered.