Today I learned that Sorbet interfaces do some magic to override how Ruby module and method overloading usually works. This is great, lets take a look!
We had a base class lets call it SomeBaseClass and it implemented a method like api_options.
So we had the following and OurClass#api_options was 'correctly' using the
implementation from SomeBaseClass
include ApiInterface
endBut what was interesting is ApiInterface was defined to need a
api_options method, which looks like this
sig { abstract.returns(ApiOptions) }
; endWithout all the Sorbet stuff in the sig that's an empty method definition which would
just return nil everytime. Without Sorbet we'd expect OurClass#api_options to return
nil since this version would be the last one defined.
However, Sorbet is doing the 'right' thing and calling the actual implementation from our base class! It kind of has to, or else it's interfaces would be hard to work with. But its good to confirm, and write down for next time I run into this!
I dug a bit and found some code to replace a method and some to call the original implementation, so I assume some combination of these is how Sorbet pulls off this trick. Maybe I'll dig deeper and turn this into a full post in the future.
My weekly newsletter tailored at developers who are eager to grow with me!
Every week will be unique, but expect topics focusing around Web Development and Rust