Rubyのinherited
https://docs.ruby-lang.org/ja/latest/method/Class/i/inherited.html
Rubyにはinheritedというサブクラスが定義されたときにコールされるクラスメソッドがある.
存在は知っていたが使う機会が一切無かったのでいろいろ実験して調べてみた.
とりあえず使ってみる
class Hoge
def self.inherited(subclass)
puts 'ここでなんかできるよ'
end
end
class Fuga < Hoge
end
> ruby hoge.rb
ここでなんかできるよ
という具合でおもむろに定義しておけば継承にフックして勝手に実行される.
サブクラスのサブクラスが定義されたときも呼ばれる
class Hoge
def self.inherited(subclass)
puts 'ここでなんかできるよ'
end
end
class Fuga < Hoge
end
class Piyo < Fuga
end
> ruby hoge.rb
ここでなんかできるよ
ここでなんかできるよ
サブクラスでオーバーライドするとサブクラスのinheritedだけ呼ばれる
class Hoge
def self.inherited(subclass)
puts 'ここでなんかできるよ'
end
end
class Fuga < Hoge
def self.inherited(subclass)
puts 'Fugaのinheritedだよ'
end
end
class Piyo < Fuga
end
> ruby hoge.rb
ここでなんかできるよ
Fugaのinheritedだよ
引数にはサブクラスのクラスオブジェクトが渡される
class Hoge
def self.inherited(subclass)
puts subclass.to_s
end
end
class Fuga < Hoge
end
class Piyo < Fuga
end
> ruby hoge.rb
Fuga
Piyo
inheritedの実行タイミング
class Hoge
def self.inherited(subclass)
puts '呼ばれたよ'
end
end
puts '1'
class Fuga < Hoge
puts '2'
end
puts '3'
> ruby hoge.rb
1
呼ばれたよ
2
3
class Fuga < Hoge
この行で呼ばれるらしい.
このことを指して記事冒頭に貼ったドキュメントでは
このメソッドが呼ばれるタイミングは クラス定義文の実行直前です。
と説明している.
inherited内でのself
class Hoge
def self.inherited(subclass)
puts self.to_s
end
end
class Fuga < Hoge
end
class Piyo < Fuga
end
> ruby hoge.rb
Hoge
Fuga
まとめ
要するに「継承時に呼ばれる」という点だけが特殊でそれ以外は普通のクラスメソッドと何も変わらないらしい.
Naniyatsuというgemを作った
だいたいわかったのでお遊びでNaniyatsuというgemを作った.
リポジトリ: https://github.com/takuan-oishii/naniyatsu
RubyGems: https://rubygems.org/gems/naniyatsu
require 'naniyatsu'
class Hoge
extend Naniyatsu
end
class Fuga < Hoge
end
class Piyo < Fuga
end
Hoge.new.hoge? # => true
Fuga.new.hoge? # => true
Piyo.new.hoge? # => true
Hoge.new.fuga? # => false
Fuga.new.fuga? # => true
Piyo.new.fuga? # => true
Hoge.new.piyo? # => false
Fuga.new.piyo? # => false
Piyo.new.piyo? # => true
extendするとclass_name?
なメソッドを生やしてくれるmodule.
サブクラスのインスタンスはsuper_class_name?
にもtrueを返すので挙動のイメージはkind_of?
メソッドである.
本体はこのファイルだけで完結している.
https://github.com/takuan-oishii/naniyatsu/blob/master/lib/naniyatsu.rb
inheritedと似たメソッドのextendedも使っていていい感じに勉強になった.
余談
qiitaの話の流れ上書きやすかったので「勉強したかったから勉強してついでにgem作りました」という順番で書いたが実際は同僚が
「RailsのSTIってclass_name?
みたいなメソッド生やしてくれそうで生やしてくれないんだな」
と言うので「じゃあそういうgem作るか」という流れで始まったNaniyatsuのアイデアありきの勉強である.