1. shiopon01

    Posted

    shiopon01
Changes in title
+RubyのModuleの使い方とはいったい
Changes in tags
Changes in body
Source | HTML | Preview
@@ -0,0 +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のエラーが出ます。
+
+```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"
+```