学び直し Rubyがミニツク Part7

今日の教科書
[クラスとモジュール](http://www.minituku.net/courses/566428009/contents/117639816.html#lesson_902363652_content)

#メモ

##クラス
全てのオブジェクトは何かのクラスに所属している。

`new`：新しいオブジェクトを作るために使う。

```
ary = Array.new
p ary  #=> []
str = String.new
p str  #=> ""
```

クラスに属しているオブジェクトを作れる、このようなオブジェクトをインスタンスともいう。

`class`：オブジェクトが属しているクラスを知る。

```
ary = Array.new
p ary.class  #=> Array
```

##クラスの定義

Rubyには最初から組み込まれているクラスがある。別に新しく定義もできる。

```
class ＜クラス名＞
  ＜クラスの定義＞
end
```

クラス名の最初は大文字。

```
class HelloRuby
  def hello
    puts("Hello, Ruby!")
  end
end
greeting = HelloRuby.new
greeting.hello
```

##initializeメソッド

クラス内にinitializeを定義するとnewでインスタンスを作るときにinitializeが呼ばれる。
newに渡した引数がinitializeの引数になる。インスタンスの初期化の設定の際に、クラス内に定義して使う。

```
class Person
  # 引数に値を代入すると、デフォルト値を設定できる
  def initialize(name="Bob")
    @name = name
  end
  def name
    puts(@name)
  end
end
bob = Person.new
bob.name   #=> Bob
john = Person.new("John")
john.name  #=> John
```

インスタンスを初期化しない場合は定義しなくていい。

##インスタンス変数
「＠」がついている変数のこと。インスタンス変数はクラス内の異なるメソッドの間でも値の受け渡しができる。インスタンス変数はインスタンスごとに異なる値を扱える。

```
class Foo
  def initialize(arg)
    @foo = arg
  end
  def foo
    puts @foo
  end
  def bar
    puts @foo
  end
end
foo = Foo.new("foo")
foo.foo  #=> foo
foo.bar  #=> foo
bar = Foo.new("bar")
bar.foo  #=> bar
foo.bar  #=> bar
# 異なる値をインスタンス変数に代入している
foo.foo  #=> foo
```

##インスタンスメソッド

クラス内で定義したメソッドはインスタンスメソッドとして扱われる。そして、newでインスタンスを作ったときにそのインスタンスに追加される。インスタンスメソッドはインスタンスに対する操作を目的としているので、インスタンスをレシーバにして呼び出す。

```
class Foo
  def foo
    puts("foo")
  end
end
instance = Foo.new
instance.foo  #=> foo
```

##アクセスメソッド

オブジェクト内のインスタンス変数を外部から操作することはできない。
そのため、専用のメソッドを定義する必要がある。

```
class Person
  def name
    return @name
  end
  def name=(value)
    @name = value
  end
end
```

nameとname=は別。`name`：インスタンス変数の値を知るためのメソッド。
`name=`：インスタンス変数に代入するメソッド。

```
class Person
  def name
    return @name
  end
  def name=(value)
    @name = value
  end
end
john = Person.new
john.name = "John"
p john.name  #=> John
bob = Person.new
bob.name = "Bob"
p bob.name   #=> Bob
```

 > このようにRubyのオブジェクトが持っているインスタンス変数の値を調べるにはメソッドを定義しないといけません。そのため、このようなメソッドを定義するための機能がRubyには用意されています。attr_reader :method　参照のみ可能にする
attr_writer :method　変更のみ可能にする
attr_accessor :method　参照と変更の両方を可能にする

アクセスメソッドと呼び、クラス内に定義すると引数に指定したメソッド名と同じ名前のインスタンス変数とメソッドが定義される。そのメソッドを呼び出して、つくられたインスタンス変数を扱う。

```
class Greeting
  attr_reader :hello
  attr_writer :bye
  attr_accessor :pardon
end
greeting = Greeting.new
greeting.hello  #=> nil
greeting.bye = 42
greeting.pardon = "sorry"
p greeting.pardon  #=> sorry
```

###末尾の記号
 - 等号 (=)
 - 疑問符 (?)
 - 感嘆符 (!)

これらをメソッドに定義するときにつけることができる。

 > これらの記号をメソッド名の末尾に付けたメソッドは、どのような機能を持っているのかを表しています。ただし、記号が表しているメソッドの機能を備えていたとしても、必ずメソッド名の末尾に記号が付いているわけではありません。

####等号
メソッドの末尾につけると代入できることを表す。アクセスメソッドと同様、セッターメソッド。

```
class Person
  # メソッド名の末尾に「=」がないメソッド定義
  def result(value)
    @name = value
  end
end
bob = Person.new
# この形式で値を変更できない
bob.result = "Bob"
NoMethodError: undefined method `result=' for #<Person:0xb7bdb520>
        from (irb):11
        from :0
```

####疑問符
メソッドの末尾につけると真偽値を返すことを表す。

```
p @foo       #=> nil
p @foo.nil?  #=> true
@foo = "foo"
p @foo.nil?  #=> false
```

####感嘆符
レシーバを変えるメソッドは破壊的なメソッドとよぶ。このメソッドの末尾に!をつける習慣がある。
あくまで習慣なので全てについているわけではない。

 > 破壊的なメソッドは、レシーバのコピーを作ってそちらの状態を変更するよりも効率がよいように見えますが、副作用が思わぬ問題を引き起こすかもしれません。たとえば文字列の文末にある空白文字を取り除くchopメソッドがあります。

```
text = "abcde "
# メソッド呼出し
p text.chop  #=> "abcde"
p text       #=> "abcde "
# 破壊的なメソッド呼出し
p text.chop! #=> "abcde"
p text       #=> "abcde"
```

##クラスメソッド
クラスに対する操作を行うことを目的としたメソッドをクラスメソッドという。

 - def クラス名.メソッド名 〜 end
 - class << クラス名 〜 def メソッド名 〜 end end
 - class クラス名 〜 def self.メソッド名 〜 end end

このやり方でクラスメソッドを定義できる。

###「def クラス名.メソッド名 〜 end」

```
class HelloRuby
  def HelloRuby.greeting
    puts("Hello! Ruby!")
  end
end
HelloRuby.greeting  #=> Hello! Ruby!
```

###class << クラス名 〜 def メソッド名 〜 end end

```
class HelloRuby
  def foo
    puts("foo")
  end
end
class << HelloRuby
  def greeting
    puts("Hello! Ruby!")
  end
end
HelloRuby.greeting  #=> Hello! Ruby!
```

###class クラス名 〜 def self.メソッド名 〜 end end

```
class HelloRuby
  def self.greeting
    puts("Hello! Ruby!")
  end
end
HelloRuby.greeting  #=> Hello! Ruby!
```