パーフェクトRuby勉強会 10/17 4章

# まえがき
+ 今日のために書いたコードは[こちら](https://github.com/kamatama41/perfect-ruby-study)
+ 3章は[こちら](http://qiita.com/kamatama_41/private/72b13d3247a716d58f3f)

- - - 

# 4章 クラスとモジュール
## 4-1 クラス
### 4-1-2 インスタンスメソッド
#### 疑問符付きのメソッド
真偽値を返すメソッドにつける。Javaでいう「is～」メソッドの代わり
#### 感嘆符付きのメソッド
プログラマに対して注意を促したいメソッドにつける

```ruby
# 疑問符付きのメソッド
puts 2.even? # true

str = 'abc'

# 破壊的でないメソッド
puts str.reverse  # cba
puts str          # abc

# 破壊的なメソッド
puts str.reverse! # cba
puts str          # cba
```

### 4-1-8 特異メソッド
#### 特定のインスタンスにだけメソッドを追加できる

```ruby
class Foo
  def override_me
    puts 'in Foo class'
  end
end

foo = Foo.new
bar = Foo.new

# barだけにメソッドを追加する
def bar.singleton_method
  puts 'Called!!'
end

bar.singleton_method

puts '# barだけにメソッドを追加する'
begin
  foo.singleton_method
rescue => e
  puts "#{e.class}, #{e.message}"
end

puts '# 特異メソッド無いではsuperで元のクラスのメソッドを呼び出すことができる'
def foo.override_me
  super
  puts 'in singleton method'
end

foo.override_me
```

### 4-1-10 クラス定義のネスト

```ruby
# JavaでいうInnerClassのような感じでクラス定義内に書く
class My
  class SweetClass
  end
end

# こういう風にも書ける
class My::SweetClass2
end

# 呼び出し方
my_sweet_class = My::SweetClass.new
my_sweet_class2 = My::SweetClass2.new
```

## 4-2 モジュール
### 4-2-1 モジュールの特徴
+ インスタンスを生成することはできない
+ 継承することはできない

#### モジュールの用途例
+ 名前空間を作る
+ モジュールのメソッドを、あるクラスのインスタンスメソッドとして取り込む
+ モジュールのメソッドを、あるオブジェクトの特異メソッドとして取り込む
+ モジュール関数を定義して使う

#### モジュールの特異メソッドを作成する
```ruby
module Sweet
  def self.lot
    %w(brownie apple-pie bavarois pudding).sample
  end
end

puts Sweet.lot
```

### 4-2-2 メソッドをクラスのインスタンスメソッドとして取り込む
こうすることでいわゆる「Mix-in(機能を他のクラスから集める)」を実現できる

```ruby
module Greetable
  def greet_to(name)
    puts "Hello, #{name}. My name is #{self.class}"
  end
end

class Alice
  include Greetable

  # moduleのメソッドをオーバーライドできる
  def greet_to(name)
    super
    puts 'Nice to meet you!'
  end
end

alice = Alice.new
alice.greet_to 'Bob'

# 代表的な組み込みモジュールEnumerableを組み込んだ例
class FriendList
  include Enumerable

  def initialize(*friends)
    @friends = friends
  end

  def each
    for v in @friends
      yield v
    end
  end
end

friend_list = FriendList.new('Alice', 'Bob', 'Charlie')

puts friend_list.count # 3
puts friend_list.map{|v| v.upcase}.inspect  # ["ALICE", "BOB", "CHARLIE"]
puts friend_list.find{|v| /b/ === v}  # 'Bob'
```

### 4-2-3 メソッドをオブジェクトに取り込む
オブジェクトによって別の振る舞いを持たせることができる

```ruby
module Destroyer
  def introduce
    super
    puts 'I\'m destroyer.'
  end
end

module Programmer
  def introduce
    super
    puts 'I\'m programmer.'
  end
end

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

  def introduce
    puts "My name is #{@name}"
  end
end

maruyama = Person.new('maruyama')
masudaK = Person.new('masudaK')

maruyama.extend Programmer
maruyama.introduce

masudaK.extend Destroyer
masudaK.introduce
```

### 4-2-4 モジュール関数
モジュール関数の良いところが分からない・・・

```ruby
# モジュールから直接呼び出す
puts Math.sqrt(2) # 1.4142135623730951

# includeして使う
include Math
puts sqrt(2)

module MyFunctions
  def my_module_function
    puts 'Called!'
  end
  module_function :my_module_function
end

MyFunctions.my_module_function
```

- - - 
# 課題
## 課題1
### 1-1. 以下の仕様を満たすswap(n1, n2)メソッドを、Arrayクラスのインスタンスの特異メソッドとして追加する
+ 配列のn1番目の要素とn2番目の要素を交換した配列を返す(番目は0はじまり)
+ 元の配列は破壊的に変更しない
+ n1,n2が配列の要素数を超える、負の数の場合は何も起こらない

### 1-2. 以下の仕様を満たすswap!(n1, n2)メソッドを、Arrayクラスのインスタンスの特異メソッドとして追加する
+ 元の配列のn1番目の要素とn2番目の要素を交換する(番目は0はじまり)
+ n1,n2が配列の要素数を超える、負の数の場合は何も起こらない