💡
Sorbetが親クラスやincludeしたmodule内で定義された定数を認識しない場合
SorbetでRubyに型チェックを導入すると、初期の段階でSorbetが継承周りの定数を解決できないという問題に当たります。
ここではその理由や解決方法についてメモしておきます。
問題
例えば、Parent内で定義した定数をChild経由で呼び出す場合や、module内で定義した定数includeしたクラス側経由で呼び出す場合に、Sorbetがエラーを出します。
class Parent
X = 1
end
class Child < Parent
end
module Mixin
Y = 2
end
class Foo
include Mixin
end
p Child::X # -> NG: Unable to resolve constant `X`
p Foo::Y # -> NG: Unable to resolve constant `Y`
解決方法
解決方法はシンプルで、親クラスやincludeしたmodule内で定義された定数を認識しない場合は、直接定義されている場所を参照するようにしましょう。
class Parent
X = 1
end
class Child < Parent
end
module Mixin
Y = 2
end
class Foo
include Mixin
end
p Parent::X # -> OK
p Child::X # -> NG: Unable to resolve constant `X`
p Mixin::Y # -> OK
p Foo::Y # -> NG: Unable to resolve constant `Y`
理由
Sorbetはクラスの継承によってアクセスできる定数の解決をサポートしてません。
これは、SorbetのサポートしてないRubyの機能のページに書いてあります。
理由としては、型チェックのパフォーマンスの担保と理解しやすさとのことです。
確かに、継承をずっと追っていって定数を見つけるのは少し大変そうです。
includeについては上記のページに明示されていませんが、同じような理由で解決できないと思われます。
ちなみに、実際には解決は可能だがSorbetの思想上、解決しないようにしていると思われます。
というのも、Child::X
にホバーするとParent::X
への修正を提案してくれるため、Sorbet自身はXを見つけられていることになります。
手元で確認したければ、以下をご参照ください。
Sorbet Playground Link
Discussion