私は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"モデルは便利なタイプの "多重継承"を提供します。 OO純粋主義者たちはその声明に同意しないでしょうが、仕事をやり遂げることの妨げとなる純粋さを許してはいけません。
(この回答はもともとhttp://www.rubycentral.com/pickaxe/classes.html
にリンクしていましたが、そのリンクとそのドメインはもうアクティブではありません。)
RubyのModule
はある程度Javaに対応しますabstract class - インスタンスメソッドを持ち、クラスはそれから継承することができます(include
を介して、Rubyの連中はこれを "mixin"と呼びます)が、インスタンスは持ちません。他にも小さな違いがありますが、これだけの情報で十分です。
namespace:モジュールはネームスペースです ...これはJavaには存在しません;)
私はまたJavaとPythonからRubyに切り替えました、私は全く同じ質問をしたのを覚えています...
つまり、最も単純な答えは、モジュールはネームスペースであり、Javaには存在しないということです。 Javaでは、名前空間に最も近い考え方はパッケージです。
そのため、RubyのモジュールはJavaのモジュールと似ています。
class?いいえ
interface?いいえ
abstract class?いいえ
package?はい(多分)
javaのクラス内の静的メソッド:Rubyのモジュール内のメソッドと同じ
Javaでは、最小単位はクラスです。クラスの外に関数を持つことはできません。しかしRubyではこれは可能です(pythonのように)。
それでは、モジュールに何が入りますか?
クラス、メソッド、定数モジュールはその名前空間の下でそれらを保護します。
インスタンスなし:モジュールはインスタンスの作成には使用できません
Mixed ins:継承モデルはクラスには適さないことがありますが、機能的には一連のクラス/メソッド/定数をグループ化したい場合があります
Rubyのモジュールに関する規則
- モジュール名はUpperCamelCaseです
- モジュール内の定数はすべて大文字です(この規則はすべてのRuby定数で同じですが、モジュール固有のものではありません)。
- アクセス方法:使用。オペレーター
- 定数へのアクセス:use :: symbol
モジュールの簡単な例:
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つの大きな利点があります。
=>モジュールは名前空間を提供し、名前の衝突を防ぎます。名前空間は、他の人によって書かれた同じ名前の関数やクラスとの競合を避けるのに役立ちます。
=>モジュールはmixin機能を実装しています。
(KlazzのModuleを含めると、KlazzのインスタンスはModuleメソッドにアクセスできます。)
(クラスKlazzにModsメソッドへのアクセス権を与えるModでKlazzを拡張します。)
まず、まだ言及されていないいくつかの類似点。 Rubyはオープンクラスをサポートしていますが、モジュールもオープンです。結局、ClassはClass継承チェーンでModuleを継承しているので、ClassとModuleは同じような振る舞いをします。
しかし、プログラミング言語でクラスとモジュールの両方を持つことの目的は何ですか?あなたは自分自身に尋ねる必要がありますか?クラスはインスタンスを作成するための青写真となることを目的としており、各インスタンスは青写真の実現されたバリエーションです。インスタンスは、青写真(クラス)の単なる実現バリエーションです。当然のことながら、クラスはオブジェクト作成として機能します。さらに、あるブループリントを別のブループリントから派生させたいことがあるので、クラスは継承をサポートするように設計されています。
モジュールをインスタンス化することはできず、オブジェクトを作成することも、継承をサポートすることもできません。したがって、あるモジュールは別のモジュールを継承しないことに注意してください。
それでは、モジュールを言語に含めることのポイントは何ですか? Modulesの明白な使い方の一つは名前空間を作ることです、そしてあなたは他の言語でもこれに気付くでしょう。繰り返しになりますが、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モジュールのメソッドを継承していません。FruitクラスにAppleを含めると、AppleモジュールのメソッドはAppleインスタンスの先祖チェーンに追加されますが、Greenモジュールのメソッドは追加されません。 moduleはAppleモジュールで定義されています。
それでは、どうやってグリーンメソッドにアクセスできるのでしょうか。クラスに明示的に含める必要があります。
class Fruit
include Apple::Green
end
=> Fruit
> f.green
=> green
しかし、Rubyはモジュールのための別の重要な用法があります。これはMixinの機能です。これについては、SOに関する別の回答で説明します。しかしまとめると、ミックスインを使用すると、メソッドをオブジェクトの継承チェーンに定義できます。ミックスインを通じて、オブジェクトインスタンスの継承チェーン(include)またはselfのsingleton_class(extend)にメソッドを追加できます。