1. scivola

    タイポ修正

    scivola
Changes in body
Source | HTML | Preview
@@ -1,174 +1,174 @@
# Module
Rubyにはオブジェクト指向で一般的なクラス以外にも、モジュールという概念が存在します。モジュールではクラスと同じように定数やメソッドをまとめたり、クラスに組み込んで多重継承を実現したり、クラスなどをまとめることで名前空間を提供するなど、いろいろな使い方ができます。
この記事では以下の内容について解説します。
- 定数やメソッドをまとめる
- クラスに組み込んで多重継承を実現する
- 名前空間を提供する
リファレンスマニュアル(2.3.0)
http://docs.ruby-lang.org/ja/2.3.0/class/Module.html:title
# 定数やメソッドをまとめる
モジュールではクラスと同様に、定数やメソッドをまとめる機能があります。
## 定数
モジュール内で定義した定数は、モジュール名を経由して呼び出すことが可能です。
```ruby
module Mod
Version = "2.3.0"
end
Mod::Version #=> "2.3.0"
```
## インスタンスメソッド
インスタンスメソッドは定義するだけでは呼び出すことができません。module_functionメソッドを使い、メソッドをモジュール関数にすることで呼び出すことができるようになります。
```ruby
module Mod
def hello
puts 'Hello'
end
module_function :hello
end
Mod.hello #=> "Hello"
```
## クラスメソッド
モジュール内で宣言されたクラスメソッド(self. から宣言されるメソッド)はincludeやextendで拡張したクラスから呼び出すことができませんが、クラスと同様にモジュールから直接呼び出すことができます。
```ruby
module Mod
def self.hello
puts 'Hello'
end
end
Mod.hello #=> "Hello"
```
## モジュール関数とクラスメソッドの優先度
同名のモジュール関数とクラスメソッドがあった場合、後に定義されたメソッドのほうが実行されます。
```ruby
module Mod
def hello
puts 'module'
end
def self.hello
puts 'class'
end
module_function :hello
end
Mod.hello #=> "module"
```
```ruby
module Mod
def hello
puts 'module'
end
module_function :hello
def self.hello
puts 'class'
end
end
Mod.hello #=> "class"
```
# クラスに組み込んで多重継承を実現する(Mix-in)
Rubyのクラスは単一継承のみですが、モジュールをクラスに組み込むことで多重継承を可能にしています(ここだけ聞くとJavaで言うinterfaceのようですが、moduleではメソッドの機能を実装することができます)。クラスにモジュールをincludeしたりextendすることをMix-inと言い、Mix-inによってクラスの肥大化を防いだり、クラスをまたがった同じ処理を切り出して繰り返しを防ぐことができます。
モジュール関数、クラスメソッドは組み込むことができません。
## include
-includeでは、対象のクラスにincludeしたモジュールのメソッドが**インスタンスメソッド**として組み込まれます。クラスからnewで作成したインスタンスで呼び出すことができます。これをクラスメソッドとして呼びだそうとすると、undefinde methodのエラーが出ます。
+includeでは、対象のクラスにincludeしたモジュールのメソッドが**インスタンスメソッド**として組み込まれます。クラスからnewで作成したインスタンスで呼び出すことができます。これをクラスメソッドとして呼びだそうとすると、undefined methodのエラーが出ます。
```ruby
module Mod
def hello
puts 'Hello'
end
end
class Obj
include Mod
end
ins = Obj.new
ins.hello #=> "Hello"
```
## extend
extendでは、対象のクラスにextendしたモジュールのメソッドが**クラスメソッド**として組み込まれます。クラスメソッドなのでインスタンスでは呼び出すことができず、いつも通りクラスから直接呼び出します。こちらもインスタンスから呼びだそうとすればundefined methodです。
```ruby
module Mod
def hello
puts 'Hello'
end
end
class Obj
extend Mod
end
Obj.hello #=> "Hello"
```
# 名前空間を提供する
## 名前空間
ruby gemなどでは、クラス名やメソッド名の重複による使用者からのモンキーパッチを防ぐためにgemの中身を全て1つのモジュールで梱包することが多いです。
```ruby
module Name
class Hoge
def self.hello
puts 'hello'
end
end
end
Name::Hoge.hello #=> "hello"
```
## 名前空間とMix-in
モジュールを重ねることで、MIx-inに使うモジュールを名前空間内で提供することができます。
```ruby
module Name # 名前空間としてのモジュール
module Mod # Mix-inとしてのモジュール
def hello
puts 'Hello'
end
end
end
class Obj # Mix-in
extend Name::Mod
end
Obj.hello #=> "Hello"
```