Ruby.学習その6

#### 投稿目的
- 個人の学習目的で投稿していきます。
- Rubyの入門を読みながら自分なりの思考で記述しています。

#### 参考資料

[ゼロからわかる Ruby 超入門 (かんたんIT基礎講座)](https://www.amazon.co.jp/ゼロからわかる-Ruby-超入門-かんたんIT基礎講座-五十嵐/dp/4297101238/ref=sr_1_3?ie=UTF8&qid=1549614126&sr=8-3&keywords=ruby+入門)

#### initializeメソッド
- initializeメソッドを利用するとオブジェクトが新しく作られる際に自動で呼び出されるメソッドです。

```ruby
class Mac
    def initialize # オブジェクト作成時に自動で実行
       puts "Macbook Pro"
    end
end

Mac.new  #  結果: Macbook Pro
```

##### インスタンス変数の初期値を設定
- initializeメソッドを利用することでインスタンス変数の初期値を設定することができます。

```ruby
class Mac
    def initialize  #  オブジェクト作成時に自動で実行
        @name = "Macbook Pro"  # 実行されると値が代入される
    end
    def name
        @name  #  戻り値はインスタンス変数の値を返す
    end
end

hensuu = Mac.new  #  この時点でインスタンス変数に値を代入
puts hensuu.name  #  結果: Macbook Pro
```

##### initializeメソッドに引数を渡す
- インスタンス変数の初期値などをオブジェクト作成時に自由に値を決めたい場合は引数を利用することで値を決めることができる。

```ruby
class Mac
    def initialize(name) # 渡された引数を受け取って実行
        @name = name
    end
    def name
        @name 
    end
end

hensuu = Mac.new("Macbook Air") # 引数を渡す
puts hensuu.name # 結果: Macbook Air
```

#### クラスでメソッドを呼び出す
- クラスに作るメソッドには2つの種類が存在する。
    - 1つ目はインスタンスメソッド
        - インスタンスをレシーバとするメソッド。
    - 2つ目はクラスメソッド
        - クラスをレシーバとするメソッド。

```ruby
# インスタンスメソッド
hensuu.name
[1, 2, 3].size
1.even?

# クラスメソッド
Mac.new
Array.new
```

##### クラスメソッドの定義
- クラスメソッドを定義する際はメソッド名の前にself.を記述する。
- クラスメソッドはクラスが実行するのでオブジェクトを作ることなく呼び出しが可能。

```ruby
class Mac
    def self.name 
        "Macbook Proです"
    end
    
puts Mac.name  # 結果: Macbook Proです
```

##### 同じクラスのクラスメソッドを呼び出す
- クラスメソッド内で同じクラスのクラスメソッドを呼び出すにはメソッド名かself.メソッド名かクラス名.メソッド名で記述することで呼び出しが可能。

```ruby
class Mac
    def self.name
        "Macbook Pro、"
    end
    def self.pc_state
        self.name + "今起動しています。" # selfを省略してもクラス名でも実行可能
    end
end

puts Mac.pc_state #=> Macbook Pro、今起動しています。 
```

##### インスタンスメソッド内で同じクラスのクラスメソッドを呼び出す
- インスタンスメソッド内で同じクラスのクラスメソッドを呼び出すにはクラス名.クラスメソッドで呼び出すことができる。

```ruby
class Mac
    def self.name
        "Macbook Pro、"
    end
    def pc_state
        Mac.name + "今起動しています。"
    end
end

hensuu = Mac.new
puts hensuu.pc_state #=> Macbook Pro、今起動しています。
```

###### 補足: クラスメソッド内で同じクラス内でインスタンスメソッドを呼び出せない、クラスからはレシーバとなるインスタンスを決めることができないからです。

#### 継承を使ってクラスを分ける
- 継承とはクラス2にクラス1を継承することでクラス1のメソッドやインスタンスなどを改めて記述しなくても利用することができる。
- 継承するには下記のように記述する。

```ruby
class クラス名(子) < スーパークラス名(親)
```

- 継承元であるクラスをスーパークラスまたは親クラスと呼ぶ、継承先であるクラスをサブクラスまたは子クラスと呼ぶ。

```ruby
class Pc # 継承元
    def name= (text)
        @name = text
    end
    def name
        @name
    end
end

class State_Pc < Pc # 継承先
    def state= (text)
        @state = text
    end
    def state
        @state
    end
end
    
hensuu = State_Pc.new 
hensuu.name = "Mac" # 親クラスのメソッドなどを利用することができる
hensuu.state = "スリープ"
puts "#{hensuu.name}は#{hensuu.state}状態です。"
# 結果: Macはスリープ状態です。
        
```

#### ancestorsメソッド
- ancestorsメソッドを利用することで親クラスが表示できます。

```ruby
p Integer.ancestors
# 結果: [Integer, Numeric, Comparable, Object, Kernel, BasicObject]
p Array.ancestors
# 結果: [Array, Enumerable, Object, Kernel, BasicObject]
p Class.ancestors
# 結果: [Class, Module, Object, Kernel, BasicObject]
```

##### 親子のクラスで同名のメソッドを作った時
- 同名のメソッドを利用している場合は継承先(子クラス)のメソッドが利用されます。

```ruby
class Pc
    def name= (text)
        @name = text
    end
    def name  # Pcクラスでのnameメソッド
        "#{@name}です。"
    end
end

class State_Pc < Pc
    def state= (text)
        @state = text
    end
    def state
        @state
    end
    def name # State_Pcクラスでのnameメソッド
        puts "#{@name}は#{@state}状態です。"
    end
end

hensuu = State_Pc.new
hensuu.name = "Mac"
hensuu.state = "スリープ"
hensuu.name # 結果: Macはスリープ状態です。
```
##### 親クラスの同名のメソッドを子クラスで呼び出す
- 親クラスの同名メソッドを呼び出すにはsuperを利用します。

```ruby
class Pc
    def name= (text)
        @name = text
    end
    def name
        "#{@name}は"
    end
end

class State_Pc < Pc
    def state= (text)
        @state = text
    end
    def state
        @state
    end
    def name
        puts "#{super}#{@state}状態です。" # 親クラスのnameメソッドを呼び出している
    end
end

hensuu = State_Pc.new
hensuu.name = "Mac"
hensuu.state = "スリープ"
hensuu.name # 結果: Macはスリープ状態です。
```

##### private、public
- クラスで定義したメソッドを外で呼び出せないようにするためにはprivateを利用する、それをprivateメソッドと呼ぶ。
    - privateメソッドは使用してほしくないメソッドに利用することでプログラマーへ伝えるための機能。
- 外からでも呼び出せるメソッドをpublicメソッドと呼ぶ。

```ruby
class Mac
    def pc # publicメソッド
        name
    end
    private
    def name # privateメソッド
        "Macbook Pro"
    end
end

hensuu = Mac.new
puts hensuu.pc # 結果: Macbook Pro
puts hensuu.name # privateによりエラー
```

##### public、private改めて復習
- publicは外から呼び出すことが可能。
- privateは外から呼び出すことが不可能。
- privateやpublicと指定した後のメソッドは全て指定した状態になる。

``` ruby
class test
    def a # public
    end
    
    private # ここから先はprivateメソッドになる
    
    def b # private
    end
    
    def c # private
    end
```

- 両方とも単体で指定することも可能。

``` ruby
class test
    def a # public
    end
    
    private def b # bメソッドだけがprivate
    end
    
    def c # public
    end
```

##### privateクラスメソッドの定義
- クラスメソッドはdefの前にprivateと記述してもprivateメソッドにはならない。
- defの前にprivate_class_methodと記述することでprivateメソッドが定義される。

```ruby
class Mac
    private_class_method def self.state
        "スリープ"
    end
end

puts Mac.state # privateなのでエラー
```

#### モジュール
- モジュールとはシステムの一部を構成するひとまとまりの機能を持った部品。
    - モジュール名は先頭が大文字で始まるキャメルケース。
    - 下記はモジュールの定義。

```ruby
module モジュール名
end
```

-  モジュールはクラスと似ていますがクラスと違ってインスタンスを作ることができない。
-  インスタンスメソッドやクラスメソッド(正しくはモジュールメソッド)を定義することはできる。
- 下記はモジュールにメソッドを定義
 
```ruby
module Pc
    def windows # windowsメソッド定義
        @name += "OS"
    end
end # まだ何も起きません
```

- includeメソッドを利用することでモジュールを利用できる。
- モジュールは複数のクラスで利用ができる。

```ruby
module Pc
    def state 
        @name += "起動"
    end
end

class Mac
    include Pc # モジュールを追加
    def initialize(name)
        @name = name
    end
    def name
        @name
    end
end

hensuu = Mac.new("Mac")
hensuu.state # モジュールメソッドを呼び出し    
puts hensuu.name # 結果: Mac起動
```