Ruby モジュール、例外処理、メソッドの公開範囲

動作環境はMacです

##モジュール##

クラスのように、メソッドや定数をまとめられる。
関連するメソッドや、定数をまとめる場合だけに使用すると便利。
クラスとの違いは、インスタンス化できないことや、継承が行えない。

*構文*

**module モジュール名**
実行したい処理 (メソッドや定数など)
**end**

**実践**

```module.rb

module Driver
  def self.run　#メソッド定義はメソッド名の前にselfをつける
    puts "Run"
  end

  def self.stop
    puts "Stop"
  end
end

  Driver.run　#インスタンスを生成せずにモジュールから直接呼び出し
  Driver.stop
  driver = Driver.new　#インスタンスを作成し、変数に代入

  module TaxiDriver < Driver #モジュールの継承
  end

```

出力結果

```
Run
Stop
module.rb:13:in `<main>': undefined method `new' for Driver:Module (NoMethodError)#モジュールではインスタンス化はできない

module.rb:15: syntax error, unexpected '<'
  module TaxiDriver < Driver　#エラーが出る。継承はできない
```

##例外処理##

何らかの例外(予期しないエラー)が起きた時にプログラムをストップし、ユーザーにどのようなエラーが起きたのかを警告する処理。exceptionという

```exeption.rb

puts "--- Please enter an Integer. ---"#ユーザーに入力を求める
i = gets.to_i　

begin #beginで開始
puts 10 / i　
rescue => ex　#exは任意の変数名でOK。以下エラーが発生した時の処理
  puts "Error!"　#ユーザーに警告
  puts ex.message　#エラーの内容
  puts ex.class　#クラスの確認
ensure　#例外が起きても起きなくても実行される処理
   puts "end"

end
```
出力結果(正常時)

```
--- Please enter an Integer. ---
2 #2と入力
5　#10割る２の結果
end
```

出力結果(例外時)

```
--- Please enter an Integer. ---
0 #0と入力
Error!
divided by 0
ZeroDivisionError
end
```


```exeption.rb
puts "--- Please enter an Integer. ---"
i = gets.to_i

begin
puts 10 / i
puts "Hello!"　#処理を追加
rescue => ex
  puts "Error!"
  puts ex.message
  puts ex.class
ensure
   puts "end"

end
```

出力結果（正常時）

```
--- Please enter an Integer. ---
2
5
Hello!#実行される
end
```

出力結果(例外時)

```
--- Please enter an Integer. ---
0
Error!
         ⇦#処理が飛ばされる
divided by 0
ZeroDivisionError
end
```

##Rubyのコーディングルール##

[The Ruby　Style　Guide](https://github.com/rubocop-hq/ruby-style-guide)

[The Ruby　Style　Guide(日本語訳)](https://github.com/fortissimo1997/ruby-style-guide/blob/japanese/README.ja.md#%E3%83%AC%E3%82%A4%E3%82%A2%E3%82%A6%E3%83%88)

Rubyで記述する際の明確なルールというのは存在しないが、
上記サイトのように記述をすると、統一かされ特に複数人で開発する際に役立つ。

[Rubo Cop](https://github.com/rubocop-hq/rubocop)

同じ作者の上記サイトでは、コーディングルールをチェックしてくれる。

##メソッドの公開範囲##

private　クラス外からでも呼び出せる。デフォルトはこれ
protected あまり使われないので省略
private クラス内部からしか呼び出せない

**実践**

何も指定しないメソッド

```access.rb

class User
  def initialize(name) #メソッドの公開範囲に影響はない
    @name = name
  end

  def hello
    puts "Hello! I am #{@name}."
  end
end

imawano = User.new("Imawano")
imawano.hello　#class外部から呼び出し
```

出力結果

```
Hello! I am Imawano. #デフォルトがpublicなので、クラス外部からでも呼び出しが可能
```

privateメソッドを使用

```access.rb

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

  private #公開範囲をprivateに指定
    def hello
      puts "Hello! I am #{@name}."
    end
  end
#以下に書いたメソッドは全てprivateになる。

imawano = User.new("Imawano")
imawano.hello　#クラス外部から呼び出し
```

出力結果

```
access.rb:13:in `<main>': private method `hello' called for #<User:0x007fe1f48b0500 @name="Imawano"> (NoMethodError) #クラス外部から呼び出せない
```

publicメソッドからprivateメソッドを呼び出し

```access.rb

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

  def say #privateのメソッドをprivate外から呼び出すメソッド
    hello
  end

  private
    def hello
      puts "Hello! I am #{@name}."
    end
  end

imawano = User.new("Imawano")
#imawano.hello
imawano.say　#クラス外部から呼び出し
```

出力結果

```
Hello! I am Imawano. #出力された
```

---

クラス外部から直接private内のメソッドを呼び出すことはできないものの、publicで記述されているメソッド内から間接的に呼び出すことができる。このことを**カプセル化**という

---