super trong Ruby: tiếp tục method lookup, không chỉ gọi parent

super gọi implementation tiếp theo của cùng method name trong ancestor chain.

1
2
3
4
5
6
7
8
9
10
11
class Animal
def speak(sound)
"Animal: #{sound}"
end
end

class Cat < Animal
def speak(sound)
"#{super(sound)} — meow"
end
end

Truyền argument

1
2
3
super       # forward toàn bộ argument và block hiện tại
super() # không truyền argument
super(x) # truyền argument chỉ định

Khác biệt giữa supersuper() nhỏ về ký tự, lớn về behavior.

Module cũng nằm trong chain

1
2
3
4
5
6
7
8
module Logging
def call(...)
puts "before"
super
end
end

Service.prepend(Logging)

Với prepend, module đứng trước class; super đi tiếp vào implementation của class. Vì vậy nói super luôn gọi “parent class” là thiếu: nó gọi next method theo lookup chain.

Constructor

1
2
3
4
5
6
class Admin < User
def initialize(name:, role: :admin)
super(name: name)
@role = role
end
end

Forward mù toàn bộ keyword có thể làm parent nhận argument không biết. Explicit forwarding rõ hơn khi signature khác nhau.

Debug

1
2
method(:call).owner
self.class.ancestors

Nếu super raise “no superclass method”, xem owner/ancestors trước khi thêm method rỗng chỉ để lỗi im. super là navigation trong lookup chain; không có điểm tiếp theo thì Ruby không tự xây đường.