Alex Strizhak
Alex Strizhak

Reputation: 990

Unexpected behavior of the `alias_method` or `alias` keyword when usage with an inheritance

I'm getting this wired behavior when trying to use alias_method with an inheritance:

class First
  def calculate
    puts value
  end
end

class Second < First
  def result
    'Second:result'
  end
  alias_method :value, :result
end

class Third < Second
  def result
    'Third:result'
  end
end

Third.new.calculate
# => Second:result

so, we can resolve it in this way:

class First
  def calculate
    puts value
  end
end

class Second < First
  def result
    'Second:result'
  end

  def value
    result
  end
end

class Third < Second
  def result
    'Third:result'
  end
end

Third.new.calculate
# => Third:result

or this way:

class First
  def calculate
    puts value
  end
end

class Second < First
  def result
    'Second:result'
  end
  alias_method :value, :result
end

class Third < Second
  def result
    'Third:result'
  end
  alias_method :value, :result
end

Third.new.calculate
# => Third:result

but the question is: why it is not working as expected in the first case?

The inheritance is kind of "bad pattern", but it can be valuable when usage Policy inheritance with DRY in Rails, for example

Upvotes: 2

Views: 109

Answers (1)

Alex Strizhak
Alex Strizhak

Reputation: 990

Turns out that alias_method creates an alias that references the original method rather than the overwritten one.

The source with more details: https://theinternate.com/2014/02/14/inheritable-aliases-in-ruby.html


note:

It was confused for me, so that's why I decided to share it, I hope it's would be helpful for somebody, to avoid possible confusion.


note_2:

the same with the alias keyword:

class First
  def calculate
    puts value
  end
end

class Second < First
  def result
    'Second:result'
  end
  alias value result
end

class Third < Second
  def result
    'Third:result'
  end
end

Third.new.calculate
# => Second:result

can be resolved in the same way:

class First
  def calculate
    puts value
  end
end

class Second < First
  def result
    'Second:result'
  end
  alias value result
end

class Third < Second
  def result
    'Third:result'
  end
  alias value result
end

Third.new.calculate
# => Third:result

Upvotes: 2

Related Questions