【Ruby】コロン２つが複数ある処理。moduleの名前空間を活用したクラス。

個人メモです。

以下のように、コロン２つ`::`が複数使われているコードが何を示しているか順を追って理解する。

`Aaa::Bbb::Ccc::Ddd.new(引数:)`


##目次

1. [Ddd.new](#dddnew)
2. [Ddd.new(引数)](#dddnew引数)
3. [Ccc::Ddd.new](#cccdddnew)
4. [モジュールの中でクラスを定義するメリット](#モジュールの中でクラスを定義するメリット)
5. [Aaa::Bbb::Ccc::Ddd.new](#aaabbbcccdddnew)
6. [Aaa::Bbb::Ccc::Ddd.new(引数)](#aaabbbcccdddnew引数)
7. [引数名を指定して渡す](#引数名を指定して渡す)
8. [（補足）moduleとclass名を::を使って定義する](#補足moduleとclass名をを使って定義する)



<br>
##Ddd.new
まずはシンプルな`Ddd.new`の理解。
これは、クラス（Ddd）のインスタンスを新たに生成している。

クラスDddの中に定義されているインスタンスメソッドを呼び出すために必要な処理となる。

```ruby:
#クラス定義
class Ddd
  def hello
    p "hello!!!"
  end
end


Ddd.new.hello
#出力
"hello!!!"

c = Ddd.new
c.hello
#出力
"hello!!!"
```

インスタンスに直でメソッドを実行しても、インスタンスを変数に格納してメソッドを実行してもどちらでもOK。

・`クラス名.new.メソッド名`


<br>
**▼引数がない場合**

クラス内のメソッドに引数が設定されていない場合は、newで引数を渡す必要がない。

不要な引数を渡すとエラーになる。

```ruby:エラー例
Ddd.new.hello("aaa")
ArgumentError (wrong number of arguments (given 1, expected 0))
```


<br>
##Ddd.new(引数)
次にnewメソッドに引数がある場合。newの引数は指定したクラスに渡される。

クラス内で定義したメソッドに引数が必要な場合に使う。

```ruby:
class Ddd
  def hello2(name)
    p "hello #{name}"
  end
end

Ddd.new.hello2("aaa")
#出力
"hello aaa"
```


<br>
##Ccc::Ddd.new
次に`::`が一つある場合。クラス名の前の２つのコロンは、そのクラスが属しているmodule名を表している。

`モジュール名::クラス名.new`

```ruby:
module Ccc
  class Ddd
    def hello3
      p "Ccc::Dddのhello3"
    end
  end
end

Ccc::Ddd.new.hello3
#出力
"Ccc::Dddのhello3
```

###モジュールの中でクラスを定義するメリット
classの外にmoduleを記述するメリットは、moduleが名前空間として機能するため、異なる名前空間で同じメソッド名を使うことができる。

**▼実例**
moduleを名前空間として利用すると、同じクラス名、同じメソッド名の処理を複数記述することができる。

```ruby:
#####moduleCcc
module Ccc
  class Ddd
    def hello3
      p "Ccc::Dddのhello3"
    end
  end
end

#####moduleZzz
module Zzz
  class Ddd
    def hello3
      p "Zzz::Dddのhello3"
    end
  end
end


##呼び出し
Ccc::Ddd.new.hello3
=> "Ccc::Dddのhello3"

Zzz::Ddd.new.hello3
=> "Zzz::Dddのhello3"
```

module Cccの中のクラス(Ddd)と処理を呼び出したい場合は、`Ccc::Ddd.new.メソッド名`となる。

同様に、module Zzzの中のクラス(Ddd)と処理を呼び出したい場合は、`Zzz::Ddd.new.メソッド名`となる。



<br>
##Aaa::Bbb::Ccc::Ddd.new
複数のmoduleの中にclassを埋め込んだ場合、呼び出し時は、`モジュール名::`を複数つなげる。

```ruby:
module Aaa
  module Bbb
    module Ccc
      class Ddd
        def hello
          p "Aaa::Bbb::Ccc::Dddのhelloメソッド"
        end
      end
    end
  end
end

##メソッド呼び出し
Aaa::Bbb::Ccc::Ddd.new.hello
=> "Aaa::Bbb::Ccc.Dddのhelloメソッド"
```



<br>
##Aaa::Bbb::Ccc::Ddd.new(引数)
引数ありの場合は、クラス内の処理に引数が必要とされていればいい。


```ruby:
module Aaa
  module Bbb
    module Ccc
      class Ddd
        def hello(name)
          p "hello #{name}さん。Aaa::Bbb::Ccc::Dddのメソッドです"
        end
      end
    end
  end
end

##メソッド呼び出し
Aaa::Bbb::Ccc::Ddd.new.hello("aaa")
=> "hello aaaさん。Aaa::Bbb::Ccc::Dddのメソッドです"
```


<br>
##引数名を指定して渡す
キー引数 `キー名:`を使うと、どこにどの値を渡すかを指定することができる。

`Aaa::Bbb::Ccc::Ddd.new(引数:)`

```ruby:
module Aaa
  module Bbb
    module Ccc
      class Ddd
        def hello(name1:, name2:)
          p "hello #{name1}さんと#{name2}さん"
        end
      end
    end
  end
end

Aaa::Bbb::Ccc::Ddd.new.hello(name2: "zzz", name1: "yyy")
=> "hello yyyさんとzzzさん"
```

キー引数で指定すれば、同不順で引数を渡せる。


<br>
##（補足）moduleとclass名を::を使って定義する
moduleとclass名を定義する際に`::`を使うこともできる。

```ruby:classの場合
class Aaa::Bbb
  def hello(name)
    p "hello #{name} !!!"
  end
end

Aaa::Bbb.new.hello("aaa")
=> "hello aaa !!!"
```

```ruby:moduleの場合
module Aaa::Yyy
  class Zzz
    def hello(name)
      p "hello #{name} !!!"
    end
  end
end

Xxx::Yyy::Zzz.new.hello("bbb")
=> "hello bbb !!!"
```