Rubyの勉強まとめ2(メソッドとクラス)

# はじめに
[前回](https://qiita.com/minuro/items/a1687613e7cd837c1505)の続きです。
今回は、メソッドとクラスについてです。
勉強時のRubyのバージョンはruby2.5.0です。

# メソッドの定義
メソッドの定義は`def "メソッド名" 〜 end`で記述します。
引数を使用する場合は、メソッド名の後ろに`()`をつけて、カンマ区切りで指定します。
また、引数にはデフォルト値を指定することができます。

```rb
def method
  puts "hoge"
end

method #=> "hoge"
```

```rb
def method(str)
  puts str
end

method #=> エラー
method("hoge") #=> "hoge"
```

```rb
def method(str = "hoge")
  puts str
end

method #=> "hoge"
method("sample") #=> "sample"
```
メソッドの引数にはラベルを指定して渡すこともできます。
以下のように、`("ラベル名": "デフォルト値")`で記述します。
この場合は、引数の順番を考慮する必要が無くなります。

```rb
def method(str1: "one", str2: "two")
  puts "#{str1}, #{str2}"
end

method #=> "one, two"
method(str2: "hoge") #=> "one, hoge"
method(str2: "hoge2", str1: "hoge1") #=> "hoge1, hoge2"
```
メソッドの引数には可変長の引数を渡すことができます。
以下のように、引数の先頭に`*`をつけることで、引数を配列の形で受け取ることができます。
また、`**`のように*を2つつけることで、ハッシュの形で受け取ることができます。

```rb
def method(*values)
  puts "#{values}"
end

method(1, 2, 3, 4, 5) #=> "[1, 2, 3, 4, 5]"
```

```rb
def method(**values)
  puts values
end

method(id: 1, name: "hoge") #=> "{:id=>1, :name=>"hoge"}"
```

# メソッドの戻り値
メソッドの戻り値は、メソッド内の最後の行の結果を自動的に返します。
`return`を使用することで、その値を返すことができます。

```rb
def method(str = "")
  if str == ""
    return "hoge1"
  end
  "hoge2"
end

puts method #=> "hoge1"
puts method("hoge") #=> "hoge2"
```

# クラスの定義
クラスの定義は、`class "クラス名" 〜 end`で記述します。
また、`initialize`メソッドを定義することで、インスタンス生成時に動作させる処理を記述できます。

```rb
class Sample
  def initialize
    puts "init"
  end
end

sample = Sample.new #=> "init"
```

# インスタンス変数
インスタンス変数は、インスタンス内で使用される変数です。
`@"変数名"`のように変数名の先頭に`@`をつけて記述します。
また、インスタンス変数にはインスタンスから直接アクセスすることはできず、以下のように`変数名`メソッドと`変数名=`メソッドでアクセサーを作成します。

```rb
class Sample
  def initialize(name = "default")
    @name = name
  end

  def name
    @name
  end

  def name=(name)
    @name = name
  end
end

sample = Sample.new
puts sample.name #=> "default"
sample.name = "hoge"
puts sample.name #=> "hoge"
```

また、上記のような記法では記述が長くなってしまうため、以下のように、`attr_accessor :"変数名"`のように簡潔に記述できます。
この記述は、カンマ区切りで複数同時に記述できます。
以下の内容は、上記のものと同じ内容になります。

```rb
class Sample
  attr_accessor :name
  def initialize(name = "default")
    @name = name
  end
end

sample = Sample.new
puts sample.name #=> "default"
sample.name = "hoge"
puts sample.name #=> "hoge"
```

# クラス変数
クラス変数は、そのクラスのインスタンス間で共有される変数です。
`@@"変数名"`のように変数名の先頭に`@@`をつけて記述します。

```rb
class Sample2
  @@name = "hoge"
  def method(str)
    @@name = str
  end

  def name
    puts @@name
  end
end

sample1 = Sample2.new
sample1.name #=> "hoge"
sample1.method("hoge1")
sample1.name #=> "hoge1"

sample2 = Sample2.new
sample2.name #=> "hoge1"
sample2.method("hoge2")
sample2.name #=> "hoge2"
sample1.name #=> "hoge2"
```

# クラスメソッド
クラスメソッドはインスタンスを生成せずに、クラスから直接呼び出すことができるメソッドです。
逆に、インスタンスから呼び出すことはできません。
`def self."メソッド名" 〜 end`と記述します。
また、`class << self 〜 end`内にメソッドを記述することでも定義できます。こちらの記述の場合は、複数のメソッドをまとめて記述できます。
以下の2つのプログラムは同じ内容です。

```rb
class Sample 
  def self.method
    puts "hoge"
  end
end

Sample.method #=> "hoge"
Sample.new.method #=> エラー
```

```rb
class Sample 
  class << self
    def method
      puts "hoge"
    end
  end
end

Sample.method #=> "hoge"
Sample.new.method #=> エラー
```

# インスタンスメソッド
インスタンスメソッドは、生成したインスタンスや同じクラス内の別のメソッドから呼び出すことができます。
クラス内にそのままメソッドを定義することで記述できます。

```rb
class Sample
  def method 
    puts "hoge"
  end

  def method_two
    method
  end
end

sample = Sample.new
sample.method #=> "hoge"
sample.method_two #=> "hoge"
```
また、アクセス修飾子を記述することができます。
以下のように`private`や`protected`以降に記述したメソッドはそのアクセス修飾子で制限されます。
何も記述していないものはpublicになります。

```rb
class Sample
  def method
    method_private
    method_protected
  end

  private
  def method_private
    puts "private"
  end

  protected
  def method_protected
    puts "protected"
  end
end

sample = Sample.new
sample.method #=> "private"
              #=> "protected"
sample.method_private #=> エラー
sample.method_protected #=> エラー
```

# クラスの継承
クラスの継承は、`"子クラス名" < "親クラス名"`で記述します。

```rb
class Parent
  def method
    puts "parent method #{@str}"
  end
end

class Child < Parent
  def initialize(str)
    @str = str
  end
end

child = Child.new("sample")
child.method #=> "parent method sample"
```
親クラスのメソッドを子クラスで上書き（オーバーライド）できます。
メソッド名が同じであれば、引数が違っていてもオーバーライドされます。
また、オーバーライド元の親クラスのメソッドは`super`で呼び出せます。

```rb
class Parent
  def method
    puts "parent method #{@str}"
  end
end

class Child < Parent
  def initialize(str)
    @str = str
  end

  def method
    super
    puts "child method #{@str}"
  end
end

child = Child.new("sample")
child.method #=> "parent method sample"
             #=> "child method sample"
```