質問
私は Java 出身で、今は Ruby をよく使っています。
私がよく知らない言語機能の 1 つは、 module
. 。一体何なのか気になります module
いつ使用するのか、なぜ使用するのか module
を超えて class
?
解決
最初の答えは良いものであり、構造的な答えを与えますが、別のアプローチはあなたが何をしているのかを考えることです。モジュールとは、複数のクラスで使用できるメソッドを提供することです-それらを「ライブラリ」と考えてください。 (Railsアプリで見られるように)。クラスはオブジェクトに関するものです。モジュールは機能に関するものです。
たとえば、認証および承認システムはモジュールの良い例です。認証システムは複数のアプリレベルのクラスで機能します(ユーザーは認証され、セッションは認証を管理し、他の多くのクラスは認証状態に基づいて異なる動作をします)。したがって、認証システムは共有APIとして機能します。
複数のアプリ間でメソッドを共有している場合にもモジュールを使用できます(ここでもライブラリモデルが適しています)。
他のヒント
╔═══════════════╦═══════════════════════════╦═════════════════════════════════╗
║ ║ class ║ module ║
╠═══════════════╬═══════════════════════════╬═════════════════════════════════╣
║ instantiation ║ can be instantiated ║ can *not* be instantiated ║
╟───────────────╫───────────────────────────╫─────────────────────────────────╢
║ usage ║ object creation ║ mixin facility. provide ║
║ ║ ║ a namespace. ║
╟───────────────╫───────────────────────────╫─────────────────────────────────╢
║ superclass ║ module ║ object ║
╟───────────────╫───────────────────────────╫─────────────────────────────────╢
║ methods ║ class methods and ║ module methods and ║
║ ║ instance methods ║ instance methods ║
╟───────────────╫───────────────────────────╫─────────────────────────────────╢
║ inheritance ║ inherits behaviour and can║ No inheritance ║
║ ║ be base for inheritance ║ ║
╟───────────────╫───────────────────────────╫─────────────────────────────────╢
║ inclusion ║ cannot be included ║ can be included in classes and ║
║ ║ ║ modules by using the include ║
║ ║ ║ command (includes all ║
║ ║ ║ instance methods as instance ║
║ ║ ║ methods in a class/module) ║
╟───────────────╫───────────────────────────╫─────────────────────────────────╢
║ extension ║ can not extend with ║ module can extend instance by ║
║ ║ extend command ║ using extend command (extends ║
║ ║ (only with inheritance) ║ given instance with singleton ║
║ ║ ║ methods from module) ║
╚═══════════════╩═══════════════════════════╩═════════════════════════════════╝
誰もまだこれを言っていないことに驚いています。
質問者はJavaのバックグラウンドから来た(そして私もそうだった)ので、ここに役立つアナロジーがあります。
クラスは、単にJavaクラスのようなものです。
モジュールは、Javaの静的クラスに似ています。 Javaの Math
クラスについて考えてください。インスタンス化せず、静的クラスのメソッドを再利用します(例: Math.random()
)。
基本的に、モジュールはインスタンス化できません。クラスにモジュールが含まれる場合、クラスメソッドだけでなくすべてのモジュールメソッドへのアクセスを提供するプロキシスーパークラスが生成されます。
モジュールは複数のクラスに含めることができます。モジュールは継承できませんが、この" mixin"モデルは、「多重継承」という便利なタイプを提供します。オブジェクト指向の純粋主義者はその声明に反対しますが、仕事を終わらせるために純粋さを妨げないでください。
(この回答は元々 http://www.rubycentral.com/pickaxe/classes.html
にリンクされていましたが、そのリンクとそのドメインはアクティブではありません。)
Module
は、ある程度Javaに対応しています抽象クラス-インスタンスメソッドを持ち、クラスはそれから継承できます( include
、Rubyの連中はそれを「ミクシン」と呼んでいますが)インスタンスはありません。他にも小さな違いがありますが、これだけの情報で十分です。
namespace:モジュールは名前空間です ... Javaには存在しません;)
また、JavaとpythonからRubyに切り替えました。まったく同じ質問があったことを覚えています...
最も簡単な答えは、モジュールは名前空間であり、Javaには存在しないということです。 Javaでは、名前空間に最も近い考え方はパッケージです。
ルビーのモジュールはjava:
のようなものです
クラス?いいえ
インターフェース?いいえ
抽象クラス?いいえ
パッケージ?はい(おそらく)
Javaのクラス内の静的メソッド:rubyのモジュール内のメソッドと同じ
Javaでは、最小単位はクラスです。クラスの外部に関数を置くことはできません。ただし、Rubyではこれが可能です(Pythonなど)。
では、モジュールには何が入りますか?
クラス、メソッド、定数。モジュールはその名前空間でそれらを保護します。
インスタンスなし:モジュールを使用してインスタンスを作成することはできません
混合イン:継承モデルはクラスに適さない場合がありますが、機能面ではクラス/メソッド/定数のセットをグループ化したい
Rubyのモジュールに関するルール:
-モジュール名はUpperCamelCase
です
-モジュール内の定数はすべて大文字です(この規則は、モジュール固有ではなく、すべてのルビー定数で同じです)
-アクセス方法:を使用します。演算子
-アクセス定数:::シンボルを使用
モジュールの簡単な例:
module MySampleModule
CONST1 = "some constant"
def self.method_one(arg1)
arg1 + 2
end
end
モジュール内でメソッドを使用する方法:
puts MySampleModule.method_one(1) # prints: 3
モジュールの定数の使用方法:
puts MySampleModule::CONST1 # prints: some constant
モジュールに関するその他の規則:
ファイルで1つのモジュールを使用します(Rubyクラス、Rubyファイルごとに1つのクラスなど)
結論:モジュールは、静的/ユーティリティ クラスとミックスインを組み合わせたものです。
ミックスインは、「部分的な」実装の再利用可能な部分であり、新しいクラスの作成に役立つように、組み合わせて (または構成して) 組み合わせることができます。もちろん、これらのクラスは独自の状態やコードを持つこともできます。
クラス
クラスを定義するとき、データ型のブループリントを定義します。 クラスはデータを保持し、そのデータと対話するメソッドを持ち、オブジェクトのインスタンス化に使用されます。
モジュール
-
モジュールは、メソッド、クラス、および定数をグループ化する方法です。
-
モジュールには、2つの大きな利点があります:
=>モジュールは名前空間を提供し、名前の衝突を防ぎます。 名前空間は、他の誰かが書いた同じ名前の関数やクラスとの競合を避けるのに役立ちます。
=>モジュールはミックスイン機能を実装します。
(Klazzのモジュールを含むと、Klazzのインスタンスがモジュールにアクセスできます メソッド。 )
(KlazzをModで拡張し、クラスKlazzにModsメソッドへのアクセスを提供します。)
最初に、まだ言及されていないいくつかの類似点。 Rubyはオープンクラスをサポートしていますが、モジュールもオープンです。結局のところ、クラスはクラス継承チェーンのモジュールから継承するため、クラスとモジュールには同様の動作があります。
しかし、プログラミング言語でクラスとモジュールの両方を使用する目的は何ですか?クラスは、インスタンスを作成するための設計図になることを目的としており、各インスタンスは設計図の実現されたバリエーションです。インスタンスは、ブループリント(クラス)の実現されたバリエーションです。当然、クラスはオブジェクト作成として機能します。さらに、あるブループリントを別のブループリントから派生させたい場合があるため、クラスは継承をサポートするように設計されています。
モジュールはインスタンス化できず、オブジェクトを作成せず、継承をサポートしません。したがって、あるモジュールが別のモジュールから継承しないことを忘れないでください!
では、言語でモジュールを使用する意味は何ですか?モジュールの1つの明らかな使用法は、名前空間を作成することです。他の言語でもこれに気付くでしょう。繰り返しますが、Rubyの素晴らしい点は、モジュールを(クラスと同様に)再び開くことができることです。そして、これは異なるRubyファイルで名前空間を再利用したい場合の大きな使い方です:
module Apple
def a
puts 'a'
end
end
module Apple
def b
puts 'b'
end
end
class Fruit
include Apple
end
> f = Fruit.new
=> #<Fruit:0x007fe90c527c98>
> f.a
=> a
> f.b
=> b
ただし、モジュール間に継承はありません:
module Apple
module Green
def green
puts 'green'
end
end
end
class Fruit
include Apple
end
> f = Fruit.new
=> #<Fruit:0x007fe90c462420>
> f.green
NoMethodError: undefined method `green' for #<Fruit:0x007fe90c462420>
AppleモジュールはGreenモジュールからメソッドを継承せず、AppleをFruitクラスに含めると、AppleモジュールのメソッドはAppleインスタンスの先祖チェーンに追加されますが、Greenモジュールのメソッドは追加されません。ただし、GreenモジュールはAppleモジュールで定義されています。
では、どのようにしてグリーンメソッドにアクセスできますか?クラスに明示的に含める必要があります:
class Fruit
include Apple::Green
end
=> Fruit
> f.green
=> green
しかし、Rubyにはモジュールのもう1つの重要な使用法があります。これはMixin機能であり、SOに関する別の回答で説明します。要約すると、ミックスインを使用すると、オブジェクトの継承チェーンにメソッドを定義できます。ミックスインを介して、オブジェクトインスタンスの継承チェーン(include)またはselfのsingleton_class(extend)にメソッドを追加できます。