柴ブログ

プログラミング奮闘記

Sendagaya.rb #322 参加レポート

はじめに

現在僕はRubyRuby on Railsを勉強中ですが、勉強のためにSendagaya.rbに初めて参加してたので学んだことをまとめます。

sendagayarb.doorkeeper.jp

話題

序盤はおすすめのキーボードの話で、その後は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

デコレーターパターンとは

既存のオブジェクトに、機能を簡単に追加するためのデザインパターンのこと。

下記のページを参考にコードを読み進めていきました。

morizyun.github.io

学び

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オブジェクトにのみモジュールを追加することで、FooBarモジュールのメソッドが使えるようになっています。

感想

今回初めて参加させて頂いて、学びが多かった反面、理解できない部分もありまだまだ勉強が足りないことを痛感しました。 こうやって改めてまとめていくと自分の知識として定着していくので、勉強会参加→ブログにまとめるという作業は今後も継続したいと思います。

デザインパターンは初めて拝見しましたがとても面白く、かつロジックを組み立てたりコードリーディングに役立ちそうなので少しずつ触れていきたいです。

今回の勉強会では自分は聞きに徹することしかできなく悔しく悲しい...。 いずれ会話に参加できるようどんどん成長していきたいと思えた時間でした。

Sendagaya.rbは頻繁に活動しているのでまたお邪魔したいと思います。

参考