勉強用資料

 ローカル変数
---
変数名には英数字やアンダーバー（_）が使える。
先頭の文字を数字にできない。
メソッドやクラス、モジュールの中で定義された範囲内でのみ参照できる。
定義された場所以外からは参照できない

```ruby:qiita.rb

name = name
```
インスタンス変数
---
変数名の先頭に @ をつける。
クラスから生成されるインスタンスの範囲内で参照できる。
同じクラスから生成されたインスタンスであっても、別のインスタンスの変数は参照できない。

```ruby:qiita.rb

  @name = name
```

---

クラスインスタンス変数
---
変数名の先頭に @ をつける（インスタンス変数と同じだが、定義する場所が違う）。
クラス定義式内で定義する。
クラスメソッドから参照できる。インスタンスメソッドからは参照できない。

```ruby:qiita.rb

class Product
  @name = 'Product'
end

class DVD < Product
  @name = 'DVD'

  def self.name
    # クラスインスタンス変数を参照
    @name
  end

  def upcase_name
    # インスタンス変数を参照
    @name.upcase
  end
end

Product.name    #=> "Product"
DVD.name        #=> "DVD"

product = Product.new('A great movie')
product.name    #=> "A great movie"

dvd = DVD.new('An awesome film')
dvd.name        #=> "An awesome film"
dvd.upcase_name #=> "AN AWESOME FILM"

Product.name    #=> "Product"
DVD.name        #=> "DVD"

```

クラス変数
---
変数名の先頭に @@ をつける。
クラスと そこから生成されるインスタンスの範囲内で参照できる。別のインスタンスであっても同じクラスから生成されたものであれば、変数が共有できる。
継承したクラスでも変数を参照できる。
グローバル変数
Ruby標準の組み込み変数

```ruby:qiita.rb

class Product
  @@name = 'Product'

  def self.name
    @@name
  end

  def initialize(name)
    @@name = name
  end

  def name
    @@name
  end
end

class DVD < Product
  @@name = 'DVD'

  def self.name
    @@name
  end

  def upcase_name
    @@name.upcase
  end
end

# DVDクラスを定義したタイミングで@@nameが"DVD"に変更される
Product.name #=> "DVD"
DVD.name     #=> "DVD"

product = Product.new('A great movie')
product.name #=> "A great movie"

# Product.newのタイミングで@@nameが"A great movie"に変更される
Product.name #=> "A great movie"
DVD.name     #=> "A great movie"

dvd = DVD.new('An awesome film')
dvd.name        #=> "An awesome film"
dvd.upcase_name #=> "AN AWESOME FILM"

# DVD.newのタイミングで@@nameが"An awesome film"に変更される
product.name #=> "An awesome film"
Product.name #=> "An awesome film"
DVD.name     #=> "An awesome film"

```
グローバル変数
---
変数名の先頭に $ をつける。
プログラム内のどこからでも宣言・参照ができる。
全体のプログラムに影響を与える可能性があるため、変数名が重複しないかチェックしたり、変数の値を変更して思わぬ場所でバグを生んだりしないように注意が必要。

```ruby:qiita.rb

# グローバル変数の宣言と値の代入
$program_name = 'Awesome program'

# グローバル変数に依存するクラス
class Program
  def initialize(name)
    $program_name = name
  end

  def self.name
    $program_name
  end

  def name
    $program_name
  end
end

# $program_nameにはすでに名前が代入されている
Program.name #=> "Awesome program"

program = Program.new('Super program')
program.name #=> "Super program"

# Program.newのタイミングで$program_nameが"Super program"に変更される
Program.name  #=> "Super program"
$program_name #=> "Super program"

```
まとめ
---
**ローカル変数**は、メソッドやクラス、モジュールの中で定義された範囲内でのみ参照できる。
**インスタンス変数**は、変数名の先頭に @ をつけ、クラスから生成されるインスタンスの範囲内で参照できる。
**クラスインスタンス変数**は、変数名の先頭に @ をつけ、クラス定義式内で定義することで、クラスメソッドから参照できる。
**クラス変数**は、変数名の先頭に @@ をつけ、クラスと そこから生成されるインスタンスの範囲内で参照できる。継承したクラスでも参照できる。
**グローバル変数**は、変数名の先頭に $ をつけ、プログラム内のどこからでも宣言・参照ができる

エイリアスメソッドの定義
---
**alias 新しい名前　元の名前**
独自に作成したクラスにもエイリアスメソッドを定義できる。

同じ動作をする.lengthと.size

```ruby:qiita.rb

s = 'Hello'
s.length #=> 5
s.size   #=> 5
```
greetingを定義

```ruby:qiita.rb
class User
  def hello
    'Hello!'
  end

  # helloメソッドのエイリアスメソッドとしてgreetingを定義する
  alias greeting hello
end

user = User.new
user.hello    #=> "Hello!"
user.greeting #=> "Hello!"

```

メソッドの削除
---
**undef 削除するメソッドの名前**

```ruby:qiita.rb

class User
  # freezeメソッドの定義を削除する
  undef freeze
end
user = User.new
# freezeメソッドを呼び出すとエラーになる
user.freeze #=> NoMethodError: undefined method `freeze' for #<User:0x007fea4d0c4d08>
```
ネストしたクラスの定義
---
**class 外側のクラス
　　class 内側のクラス
　　end
  end**

クラスの内部に別のクラスを定義できる。

```ruby:qiita.rb

class User
  class BloodType
    attr_reader :type

    def initialize(type)
      @type = type
    end
  end
end

blood_type = User::BloodType.new('B')
blood_type.type #=> "B"

```
演算子の挙動を独自に再定義する
---

```ruby:qiita.rb

class User
  # =で終わるメソッドを定義する
  def name=(value)
    @name = value
  end
end

user = User.new
# 変数に代入するような形式でname=メソッドを呼び出せる
user.name = 'Alice'
```
例として==を再定義してみよう

```ruby:qiita.rb

class Product
  attr_reader :code, :name

  def initialize(code, name)
    @code = code
    @name = name
  end
end
```
このように動作して欲しい

```ruby:qiita.rb

# aとcが同じ商品コード
a = Product.new('A-0001', 'A great movie')
b = Product.new('B-0001', 'An awesome film')
c = Product.new('A-0001', 'A great movie')

# ==がこのように動作してほしい
a == b #=> false
a == c #=> true
```
今のままだとfalseになる。
==はobject_idが一致した時にtrueを返す仕様の為。

```ruby:qiita.rb

# 何もしないと実際はこうなる
a == b #=> false
a == c #=> false

# デフォルトでは同じobject_id（全く同じインスタンス）の場合にtrueになる
a == a #=> true
```
Productクラスで==を再定義(オーバーライド)する。

```ruby:qiita.rb

class Product
  # 省略

  def ==(other)
    if other.is_a?(Product)
      # 商品コードが一致すれば同じProductと見なす
      code == other.code
    else
      # otherがProductでなければ常にfalse
      false
    end
  end
end
```
再定義したので==を使っても期待通りの動きになる。

```ruby:qiita.rb

a = Product.new('A-0001', 'A great movie')
b = Product.new('B-0001', 'An awesome film')
c = Product.new('A-0001', 'A great movie')

# 商品コードが一致すればtrueになる
a == b #=> false
a == c #=> true

# Product以外の比較はfalse
a == 1   #=> false
a == 'a' #=> false
```

等値を判断するメソッドや演算子を理解する
---
**equal?**
object_idが等しい場合にtrueを返す。
equal?メソッドは再定義してはだめ。

```ruby:qiita.rb

a = 'abc'
b = 'abc'
a.equal?(b) #=> false

c = a
a.equal?(c) #=> true

```
**==**
オブジェクトの内容が等しいかどうかを判断する。
データ型が違っても人間の目で見て自然であればtrueを返すように再定義することもある。

```ruby:qiita.rb

1 == 1.0 #=> true
```
**eql?**
ハッシュのキーとして2つのオブジェクトが等しいかどうかを判断する。

```ruby:qiita.rb

# ハッシュ上では1と1.0は別々のキーとして扱われる
h = { 1 => 'Integer', 1.0 => 'Float' }
h[1]   #=> "Integer"
h[1.0] #=> "Float"

# 異なるキーとして扱われるのは、eql?メソッドで比較したときにfalseになるため
1.eql?(1.0) #=> false
```

eql?メソッドを再定義した場合は「a.eql?(b)が真なら、a.hash == b.hashも真」となるようにhashメソッドも再定義しなくてはならない。

```ruby:qiita.rb

a = 'japan'
b = 'japan'
# eql?が真なら、hash値も同じ
a.eql?(b) #=> true
a.hash    #=> 1168978237820510471
b.hash    #=> 1168978237820510471

c = 1
d = 1.0
# eql?が偽なら、hash値も異なる
c.eql?(d) #=> false
c.hash    #=> -2946966815421412510
d.hash    #=> 3646131212290672247
```
**===**
主にcase文のwhen節で使われる。

```ruby:qiita.rb

text = '03-1234-5678'

case text
when /^\d{3}-\d{4}$/
  puts '郵便番号です'
when /^\d{4}\/\d{1,2}\/\d{1,2}$/
  puts '日付です'
when /^\d+-\d+-\d+$/
  puts '電話番号です'
end
#=> 電話番号です
```
このコードを実行すると内部的には

```ruby:qiita.rb

/^\d{3}-\d{4}$/ === text
```
や

```ruby:qiita.rb


/^\d{4}\/\d{1,2}\/\d{1,2}$/ === text
```
"when節のオブジェクト === case節のオブジェクト"の結果を評価している。

```ruby:qiita.rb

value = [1, 2, 3]

# 内部的には String === value、Array === value、Hash === valueの結果が評価されている
case value
when String
  puts '文字列です'
when Array
  puts '配列です'
when Hash
  puts 'ハッシュです'
end
#=> 配列です
```