Sendagaya.rb #322 参加レポート
はじめに
現在僕はRubyやRuby on Railsを勉強中ですが、勉強のためにSendagaya.rbに初めて参加してたので学んだことをまとめます。
話題
序盤はおすすめのキーボードの話で、その後はRubyのデコレーターパターンについてコードを一緒に読んでいく内容でした。
おすすめキーボード
参加者のおすすめキーボードとして以下の物をご紹介頂けた。 中には通常のキーボードを2個並べて擬似分割キーボード使用しているという猛者の方もいました。
NiZ 2019 NEW Member atom66 The Smallest Electro Capactive Bluetooth Keyboard with RGB or Non RGBwww.nizkeyboard.com
https://www.amazon.co.jp/AKEEYO-Wireless-Keyboard-%E6%97%A5%E6%9C%AC%E8%AA%9E%E3%83%9E%E3%83%8B%E3%83%A5%E3%82%A2%E3%83%AB-%E3%82%A2%E3%82%A4%E3%83%9C%E3%83%AA%E3%83%BC_66EC/dp/B07DXK9NP9/ref=as_li_ss_tl?ie=UTF8&linkCode=sl1&tag=fukajun09-22&linkId=ccf60204e724c2dbc7b3f8070d2a7ff3&language=ja_JPwww.amazon.co.jp
https://www.amazon.co.jp/-/en/Anker-Ultra-Bluetooth-Wireless-compatible/dp/B00U260UR0www.amazon.co.jp
デコレーターパターンとは
既存のオブジェクトに、機能を簡単に追加するためのデザインパターンのこと。
下記のページを参考にコードを読み進めていきました。
学び
superの書き方
上記の参考ページのデコレーターパターンではクラスの継承とメソッドのオーバーライドをしており、そこでsuper
の書き方について再度参加者のみんなで確かめ合いました。
具体的にはsuper
への引数の有無の違いについて学びました。
これはRubyリファレンスより以下の通り。
super は現在のメソッドがオーバーライドしているメソッドを呼び出します。括弧と引数が省略された場合には現在のメソッドの引数がそのまま引き渡されます。引数を渡さずにオーバーライドしたメソッドを呼び出すには super() と括弧を明示します。
1つずつ理解するためにリファレンスのサンプルコードを引用します。
class Foo def foo(arg = nil) p arg end end class Bar < Foo def foo(arg) super(5) # 5 を引数にして呼び出す super(arg) # 5 を引数にして呼び出す super # 5 を引数にして呼び出す super(arg) の略記法 arg = 1 super # 1 を引数にして呼び出す super(arg) の略記法 super() # 引数なしで呼び出す end end Bar.new.foo 5
superに引数がない場合
単にsuper
のみを書くと(引数なし)、スーパークラスの同名のメソッドが呼び出されます。サブクラスとスーパークラスでそのメソッドの引数の数が同じならこの書き方をします。
上記のサンプルコードでいうと次の部分。
class Foo def foo(arg = nil) p arg end end class Bar < Foo def foo(arg) super # スーパークラスのfooメソッドをそのまま呼び出している end end Bar.new.foo(5) # => 5
単にスーパークラスの同名のメソッドを呼び出しているのでFoo.new.foo(5)
と実行結果が同じになります。
superに引数がある場合
super
に引数を書くとそのスーパークラスのメソッドにその引数を渡した結果が返ります。
サンプルコードの次の部分。
class Foo def foo(arg = nil) p arg end end class Bar < Foo def foo(arg) super(5) # スーパークラスのメソッドの引数に5を渡して呼び出す end end Bar.new.foo # => ArgumentError (wrong number of arguments (given 0, expected 1)) Bar.new.foo(5) # => 5 Bar.new.foo(10) # => 5
これはFooクラスのfooメソッドの引数に5を渡し、その結果を返しています。Barクラスでfoo(arg)
と引数ありで定義しているためBarインスタンスでfooメソッドを引数なしで呼び出すとエラーが返ります。
また、以下のようにsuper
にスーパークラスのメソッドと同じ引数ありで呼び出すと引数なしでsuper
を書いたのと同じように単にスーパークラスのメソッドをそのまま呼び出していることになります。
class Foo def foo(arg = nil) p arg end end class Bar < Foo def foo(arg) super(arg) # スーパークラスのメソッドの呼び出し end end Bar.new.foo(5) # => 5 Bar.new.foo(10) # => 10
さらに、super()
のように書くと、引数が0個でスーパークラスのメソッドを呼び出していることになります。
サンプルコードでいうと次の部分。
class Foo def foo(arg = nil) p arg end end class Bar < Foo def foo(arg) super() # 引数が0個でスーパークラスのメソッドを呼び出し end end Bar.new.foo(5) # => nil
引数なしでfoo
メソッドを呼び出したことになりますが、Foo
クラスでfoo(arg = nil)
と定義しているため、デフォルトのnil
が返ってきます。仮にFooクラスでfoo(arg)
と定義していると、エラーになります。
class Foo def foo(arg) # 引数のデフォルト値なし p arg end end class Bar < Foo def foo(arg) super() end end Bar.new.foo(5) # => ArgumentError (wrong number of arguments (given 0, expected 1))
モジュールのextend
クラスの継承とメソッドのオーバーライドによるデコレーター機能の追加は以上でしたが、モジュールによるデコレーター機能の追加方法もあり、その際にextend
の使い方を再度学び直しました。
クラスへのextend
モジュールをクラスへextend
した場合、モジュールで定義しているメソッドをextendしたクラスでクラスメソッド(特異メソッド)として使うことができます。
Rubyのリファレンスマニュアルよりサンプルコードを引用し一部変更します。
module Bar def b 'ok Bar' end end class Klass extend Bar end p Klass.b #=> "ok Bar"
上記のコードのうち、Klass
クラスにBar
モジュールをextend
しているため、b
メソッドをクラスメソッドとして利用することができます。
オブジェクトへのextend
モジュールのextend
は特定のオブジェクトにのみにモジュールを追加することも可能です。
上記と同じくRubyリファレンスよりサンプルコードを引用します。
module Foo def a 'ok Foo' end end module Bar def b 'ok Bar' end end obj = Object.new obj.extend Foo, Bar p obj.a #=> "ok Foo" p obj.b #=> "ok Bar"
これはObject
クラスのインスタンスであるobj
オブジェクトにのみモジュールを追加することで、Foo
、Bar
モジュールのメソッドが使えるようになっています。
感想
今回初めて参加させて頂いて、学びが多かった反面、理解できない部分もありまだまだ勉強が足りないことを痛感しました。 こうやって改めてまとめていくと自分の知識として定着していくので、勉強会参加→ブログにまとめるという作業は今後も継続したいと思います。
デザインパターンは初めて拝見しましたがとても面白く、かつロジックを組み立てたりコードリーディングに役立ちそうなので少しずつ触れていきたいです。
今回の勉強会では自分は聞きに徹することしかできなく悔しく悲しい...。 いずれ会話に参加できるようどんどん成長していきたいと思えた時間でした。
Sendagaya.rbは頻繁に活動しているのでまたお邪魔したいと思います。