D IT Y

タマキ工務店のIT日記

チェリー本輪読会 第12週目まとめ

f:id:shirotamaki:20210619091936p:plain

🍒 はじめに

チェリー本輪読会の第12週目のエントリーになります。

輪読会の概要については第1週目にまとめています。

🍒 輪読会 第12週目まとめ

第7章7.10.1〜第7章7.11まで

期間:2021年08月09日〜2021年08月13日

第8章にも少し入りましたが、こちらは次週へまとめます。

エイリアスメソッドの定義

alias 新しい名前 元の名前

エイリアスメソッドを定義する場合は、事前に元のメソッドを定義しておく必要があります。

class Numbergirl
    def introduce
        "福岡市博多区から参りましたナンバーガールです”
  end
alias greeting introduce
end

numbergirl = Numbergirl.new

numbergirl.introduce
=> "福岡市博多区から参りましたナンバーガールです"
numbergirl.greeting
=> "福岡市博多区から参りましたナンバーガールです"

クラス/メソッドの定義 (Ruby 3.0.0 リファレンスマニュアル)

メソッドの削除

undef 削除するメソッドの名前

メソッドの定義をあとから削除することができます。

先程の、Numbergirlクラスを継承し、その後定義しておいたintroduceメソッドを削除してみます。

class Zazenboys < Numbergirl
    undef introduce
end

zazenboys = Zazenboys.new
zazenboys.intoroduce
: undefined method `intoroduce' for #<Zazenboys:0x00007fa552839290> (NoMethodError)

クラス/メソッドの定義 (Ruby 3.0.0 リファレンスマニュアル)

ネスト(入れ子)したクラスの定義

class 外側のクラス
    class 内側のクラス
    end
end

クラスの内部に定義したクラスは、::を使って参照できます。

外側のクラス::内側のクラス 

この形を、名前空間(ネームスペース)と呼びます。(通常はクラスよりモジュールが使われることが多いです。)

class Numbergirl
    class Zazenboys
        attr_reader :menber
        
        def initialize(member)
            @member = member
        end
    end
end

leader = Numbergirl::Zazenboys.new('向井秀徳')
leader
=> #<Numbergirl::Zazenboys:0x00007fa556873d88 @member="向井秀徳">

等値を判断するメソッドや演算子4つ

equal?

英語の意味そのままなので分かりやすいです。等しければtrueを返します。

object_idを比較しているので、代入している内容が文字列だとfalseになります。object_idが違うためです。

numbergirl = 'Band'
zazenboys = 'Band'
hakata = numbergirl 

numbergirl.equal?(zazenboys)
=> false
numbergirl.equal?(hakata)
=> true

==

オブジェクトの内容が等しいか判断します。

100 == 100.000
=> true

'a' == 'a'
=> true

'a' == 'A'
=> false

'a' == :a
=> false

foo = 'hoge'
=> "hoge"

bar = 'h'+ 'o' + 'g' + 'e'
=> "hoge"

foo == bar
=> true

eql?

== とは別に、値が同じどうかを判定することができます。

== との違いは、ハッシュ値が等しいかどうかで判断する点です。

hashメソッドで、ハッシュ値を確認し同じであれば、trueになります。

numbergirl = 'Band'
zazenboys = 'Band'

numbergirl.hash
=> 1476835131188092417
zazenboys.hash
=> 1476835131188092417
numbergirl.eql?(zazenboys)
=> true

Hash#hash (Ruby 3.0 リファレンスマニュアル)

===

左辺が単独のStringやIntegerオブジェクトの場合は、==と同じように判断されます。

左辺がClassオブジェクトの場合は、右辺がそのクラスのインスタンスであるかどうかを判断します。

左辺が正規表現の場合は、=~と同じようにマッチしたかどうかを判断します。=~ を使って正規表現を比較する

100 === 100.00
=> true
'a' === 'A'
=> false
'a' === 'a'
=> true

/\w{6}-\d{3}/ === 'MONGOL-800'
=> true

また、case文のwhen節の内部で行われている処理ですが、===で判断されています。

# case文の公式
case 比較したいオブジェクト
when A
  # 処理
when B
  # 処理
else 
    # 処理
end

# 内部で行われている処理
if A === 比較したいオブジェクト
  # 処理
elsif B === 比較したいオブジェクト
  # 処理
else
  # 処理
end
case 'foo'
    when 'foo'
        puts 'true'
    when /w{3}/
        puts 'true'
    else 
        puts 'false'
 end

# true
=> nil

case 100
    when 'foo'
        puts 'true'
    when /w{3}/
        puts 'true'
    else 
        puts 'false'
 end

# false
=> nil

オープンクラス

Rubyはクラスの継承に制限がありません。String や Integer といった基本的なクラス(組み込みクラス)も自由に改変できます。定義済みのクラスへ、メソッドを追加することも上書きすることも可能です。Rubyのクラスは変更に対してオープンなので、「オープンクラス」と呼ばれています。

以下、Arrayクラスを継承させた独自のクラスになります。

class Numbergirl < Array
end

band = Numbergirl.new()
=> []
band << '向井秀徳'
=> ["向井秀徳"]
band << '田渕ひさ子'
=> ["向井秀徳", "田渕ひさ子"]
band
=> ["向井秀徳", "田渕ひさ子"]
band.class
=> Numbergirl

# 継承しないとエラーになる。
class Numbergirl
end

band = Numbergirl.new()
=> #<Numbergirl:0x00007f84d916b420>
band << '向井秀徳'
: undefined method `<<' for #<Numbergirl:0x00007f84d916b420> (NoMethodError)

モンキーパッチ

組み込みクラスやメソッドを追加したり変更したりします。このように自分が期待する挙動へ変更することを、モンキーパッチといいます。

class Numbergirl
    def initialize(name)
            @name = name
    end

    def introduce
        "#{@name}です"
    end
end

band = Numbergirl.new('ナンバーガール')
band.introduce
=> "ナンバーガールです"

# モンキーパッチを当てて、希望する挙動へ変更する。
class Numbergirl
    def introduce
        "福岡市博多区から参りました#{@name}です"
    end
end

band.introduce
=> "福岡市博多区から参りましたナンバーガールです"

原則として、オープンクラス、モンキーパッチには頼らない

オープンクラス、モンキーパッチは非常に強力です。誤って使用してしまうとプログラム全体に不具合を生じさせてしまう原因となってしまいます。

原則として、まずはオープンクラス、モンキーパッチに頼らずにプログラムが書けないか考える必要があります。

大いなる力には、大いなる責任が伴うことを忘れてはいけない。 Matz

特異メソッド (singleton メソッド)

Rubyはすべてがオブジェクトなので、StringクラスやArrayクラスもオブジェクトです。そして、それらのクラスは、Classクラスインスタンスになります。

class String
end

String.class
=> Class

class Foo
end

Foo.class
=> Class

特異メソッドとは、特定のオブジェクトに紐づくメソッドのことです。 オブジェクト固有のメソッドのことで、あるオブジェクトにはあるメソッドが存在しますが、同じクラスの別のオブジェクトには存在しません。

特異メソッドはdef オブジェクト名.メソッド名で定義できます。

class Instance
  def i_method
    puts 'インスタンスメソッドです。'
  end
end

foo = Instance.new
bar = Instance.new

# 特異メソッドを定義します。
def foo.s_method
  puts '特異メソッドです。'
end

foo.i_method
=> インスタンスメソッドです。

bar.i_method
=> インスタンスメソッドです。

# オブジェクトがfooで、特異メソッドとしてs_methodを定義しているので呼び出せる。
# s_methodは、fooのみが持つ特異メソッドとして定義されている。
foo.s_method
=> 特異メソッドです。

# オブジェクトがbarと異なるため呼び出せない。(barオブジェクトにはs_methodは定義していない)
bar.s_method 
: undefined method `s_method' for #<Instance:0x00007f8474a980d0> (NoMethodError)

るりまを参照する際には、クラスメソッドではなく、特異メソッドと書かれているので置き換えて読みます。

Ruby におけるクラスメソッドというのは Class クラスのインスタンスの特異メソッドを便宜上クラスメソッドと呼んでいて、実態は特異メソッドの一種です。

ダックタイピング

もしもそれがアヒルのように歩き、アヒルのように鳴くのなら、それはアヒルである

という言葉に由来するプログラミング用語です。

オブジェクトのクラスが何であろうと、そのメソッドが呼び出せればOKとするプログラミングスタイルのことです。オブジェクトを特徴づけるのは、実際のクラスや継承関係ではなく、そのオブジェクトがどのように振る舞うか?(どんなメソッドを持っているか?)です。

class Member
    def play
        puts 'メンバーは楽器を演奏する'
 end
end

class Guitar < Member
    def play
        puts 'ギターを演奏する'
    end
end

class Bass < Member
    def play
        puts 'ベースを演奏する'
    end
end

member = Guitar.new
member.play
# => ギターを演奏する

member = Bass.new
member.play
# => ベースを演奏する

同じ名前のメソッドが複数のオブジェクトに属することをオブジェクト指向の用語で、「ポリモーフィズム」といいます。playメソッドの実行結果はそれぞれ違います。(putsの中身が違う)

ポリモーフィズム

  • 共通メインルーチンを作るための仕組み。
  • 呼び出す側のロジックを一本化する仕組み。
  • 呼び出される側の引数や戻り値の形式を統一する必要がある。

botが導入されました

今週、楽しみにしていたbotが輪読会へ導入されました〜!

botとは?

e-words.jp

choosing-someone-discord-bot(Discordのボイスチャンネルに参加しているメンバーをランダムに指名するbot

Discordの音声チャンネルで開催されている輪読会ですが、毎回、司会やドライバーなどを決める作業がありました。その都度irbを開きsampleメソッドをまわして決めていたのですが、多少の手間と煩わしさがありました。そこで、この作業をbotで代替する目的で、トミーさんが開発されていたのが今回紹介するbotになります。今までの手間がなくなり、かつエンタメ性もプラスされ、楽しく、便利になりました!

botの詳細は、トミーさん(id:eatplaynap329)のブログ、GitHubページに詳しく書かれています。

eatplaynap329.hatenablog.jp

github.com

mitaka.rbへ初参加!

輪読会メンバーの紹介で初めてmitaka.rbへ参加しました。

イベント管理アプリをモブプロで作る会でした。

Webアプリケーションの制作過程を、モブプロ形式で見ることができました。テスト駆動開発(TDD)の流れをベースに、どのように思考しコードを書いてくのか?熟練者のプログラマの手元をLIVEで見ることができ勉強になりました。Vimを使っている画面も初めて見ることができました。他にも、esaを初めて使ってみたり、いろいろ経験できよかったです。

そしてなにより、主催の@tatsuoSakurai さんや、@okuramasafumi さんがとても優しく親切で、とても雰囲気の良いコミュニティでした。ぜひまた参加したいと思います!

mitakarb.doorkeeper.jp

参考書籍

🍒 まとめ

チェリー本、最初の難関であるクラスの章が完了しました!

いや〜、大変でした。しかしその分、同時に参加した『オブジェクト指向でなぜつくるのか』輪読会ともあわせて、クラス、オブジェクト指向の基礎について学ぶことができた章でした。 今までは、「クラス怖い」「継承?クラスメソッド?」と、自信の持てなかった内容ですが、輪読会を通して理解することができ大きな自信となりました。次回は、モジュールに入ります!

では、また来週!(次回、第13週目)