モジュールのインスタンスを作成できない場合でも、モジュールにインスタンス変数を含めることができますか?以下のモジュールStacklike
の@stack
の目的は何ですか?
module Stacklike
def stack
@stack ||= []
end
end
インスタンス変数は、モジュールを含むクラスに存在するものと考えてください。物事はもう少し理にかなっています。
module Stacklike
def stack
@stack ||= []
end
def add_to_stack(obj)
stack.Push(obj)
end
def take_from_stack
stack.pop
end
end
class ClownStack
include Stacklike
def size
@stack.length
end
end
cs = ClownStack.new
cs.add_to_stack(1)
puts cs.size
「1」を出力します
以下を参照してください。
_p Ruby_VERSION
module Stacklike
def stack
@stack ||= []
end
def add_to_stack(obj)
stack.Push(obj)
end
def take_from_stack
stack.pop
end
end
class A
include Stacklike
end
a = A.new
p a.instance_variables #<~~ E
p a.instance_variable_defined?(:@stack) #<~~ A
a.add_to_stack(10) #<~~ B
p a.instance_variable_defined?(:@stack) #<~~ C
p a.instance_variables #<~~ D
_
出力:
_"1.9.3"
[]
false
true
[:@stack]
_
説明:はい、クラス内でModule
を使用する場合、class
にinclude
インスタンス変数が存在します。ただし、_[〜#〜] a [〜#〜]までは_@stack
_がまだ定義されていないため、p a.instance_variable_defined?(:@stack)
がfalse
を示していることがわかります。ポイントで[〜#〜] b [〜#〜]インスタンス変数@stackを定義しました。したがって、ポイント[〜#〜] c [〜#〜]のステートメントは、true
として出力されます。モジュール自体はモジュールインスタンス変数を作成していませんが、class
にそのモジュールが含まれていれば、class
インスタンスで作成できます。 [〜#〜] e [〜#〜]のステートメントは、_[]
_を出力しますが、インスタンス変数は定義されていませんが、行の出力が表示される場合[〜#〜] d [〜#〜]、_@stack
_が_class A
_のオブジェクトa
内にあることが証明されます。
なぜそのようなデザインですか?
これは設計であり、要件から生じる場合があります。たとえば、A
とB
という2つのチケット予約会社が使用するスタック操作コードを記述するように求められたとします。現在、A
は、顧客がサービスを提供するスタックポリシーですが、それについても正式な手続きがあります。 B
会社も、A
とは異なる独自の形式でスタックポリシーを使用しています。したがって、_class A
_および_class B
_内でStack
操作を設計する場合は、A
とB
の両方に共通の機能があるため、共通の場所に記述することをお勧めします。将来、別の会社C
が登場した場合、各A
、B
およびC
に対して同じ機能を書き換えることなく、そのモジュールをクラスに使用することもできます。より多くの考えがありますが、これが質問の最後の部分であなたの自己に答えるのに役立つことを願っています。
それがコンセプトです。それが役に立てば幸い。
乾杯!!
モジュールをクラスに含めると、そのすべてのインスタンスメソッドが実質的にHostクラスに「貼り付け」られます。あなたが持っている場合:
class Lifo
include Stacklike
end
l = Lifo.new
l.add_to_stack(:widget)
l
には、Stacklike
から取り込まれたインスタンス変数@stack
があります。
モジュールのStacklikeを他のクラスに含めると、そのインスタンス変数はそのクラスで定義されているかのように利用可能になります。これにより、モジュール自体から基本クラスのインスタンス変数を設定および処理するオプションが提供されます。