私はJavaからRubyに移行し、Rubyスコープを理解しようとしています。Rubyのクラス変数はJavaの静的変数に似ていますか?
Javaでは、クラス変数は静的変数と同じように動作するようです。この解釈は正しいのでしょうか?もしそうなら、Rubyのグローバル変数は、Javaのpublic static変数と同じですか?
私はJavaからRubyに移行し、Rubyスコープを理解しようとしています。Rubyのクラス変数はJavaの静的変数に似ていますか?
Javaでは、クラス変数は静的変数と同じように動作するようです。この解釈は正しいのでしょうか?もしそうなら、Rubyのグローバル変数は、Javaのpublic static変数と同じですか?
RubyとJavaの間にはオブジェクト指向であることが多いため類似点はたくさんありますが、そのファミリツリーは異なります。 RubyはSmalltalkに非常に頼りになりますが、JavaはC++という学校から継承します。
ここでの違いは、Rubyのpublic/private/protectedの概念はかなり弱く、ルールよりも多くの提案であり、静的メソッドや定数のようなものは言語の構文よりもパターンが多いことです。
大域変数は非常に大きく眉をひそめています。自由に使用すると、混乱の原因となります。 Rubyの方法は、名前空間のものにある:このモジュールのような
$ugly_global = 0 # Not recommended, could conflict with other code
# Ownership of this variable isn't made clear.
$ugly_global += 1 # Works, but again, it's without context.
module UglyCounter # Defines a module/namespace to live in
def self.current # Defines a clear interface to this value
@counter ||= 0 # Initializes a local instance variable
end
def self.current=(v) # Allow modification of this value
@counter = v.to_i # A chance to perform any casting/cleaning
end
end
UglyCounter.current += 1 # Modifies the state of a variable, but
# the context is made clear.
さえ薄い層があなたにこの変数からの読み出し/書き込み動作をインターセプトし、動作を変更することができます。たぶん、特定の値にデフォルト値を設定したり、値を正規化された形式に変換したりすることができます。裸の世界では、このコードをどこでも繰り返す必要があります。ここでそれを統合することができます。
クラス変数はまったく別のものです。また、このクラスのクラスとインスタンス間でデータを共有することは面倒なことがあるため、避けてください。彼らは2つの異なる文脈であり、分離は尊重されるべきです。
class MessyClass
@@shared = 0
def counter
@@shared
end
def counter=(v)
@@shared = v
end
end
これは、共有クラスレベルのインスタンス変数を使用する方法のかなり大まかな取り組みです。ここで問題となるのは、各インスタンスがクラス・コンテキストをバイパスして直接変更することです。つまり、そのクラスは無力です。これは根本的に失礼であり、インスタンスはその権限を過度に拡張しています。より良いアプローチはこれです:静的クラスメソッドが自動的にインスタンスの範囲で利用可能になる
class CleanerClass
def self.counter
@counter ||= 0
end
def self.counter=(v)
@counter = v.to_i
end
# These are reduced to simple bridge methods, nothing more. Because
# they simply forward calls there's no breach of authority.
def counter
self.class.counter
end
def counter=(v)
self.class.counter = v
end
end
多くの言語では、これは、Rubyには当てはまりません。ブリッジ/プロキシ/デリゲートメソッドを記述する必要があります。ここで使用する用語は、使用しているものによって異なります。
私はJavaに精通していませんが、私はRubyの用語で説明することができます。
Rubyでは、クラス変数の前に変数名@@
があります。それはあなたが思うように行動しません。クラス変数が作成されると、それはすべてのサブクラス間で共有されます。
グローバル変数の場合は、変数名の前に$
があります。それはまるでそれがそうであるように聞こえる、それはグローバルであり、どこにでもアクセスすることができます。
両方の変数はRubyではお勧めできません。名前の前に@
というインスタンス変数を使用して、必要な処理を行うことができます。オブジェクトに固有です。あるオブジェクトに宣言すると、別のオブジェクトには表示されません。
これがこれをクリアすることを願っています。
また、ivarsは_classオブジェクトに設定することもできます。 –
重要な違いの1つは、静的メソッドとインスタンス変数がJavaではできない方法で、クラスメソッドとインスタンス変数がRubyでやり取りする方法です。
tadmanの答えは、このコードが含まれています。世界のジャワ(およびC#の)プログラマに
class CleanerClass
def self.counter
@counter ||= 0
end
def self.counter=(v)
@counter = v.to_i
end
end
それが動作してはならないように、このコードが見えます。結局のところ、そのモデルでは、静的メソッドからインスタンス変数にアクセスするというアイデアはインコヒーレントであり(コンパイルもされません)全体のポイントは、あなたがインスタンスを持っていないということです!
しかし、Rubyでは、すべてのクラス定義自体がClass
型のインスタンスです。 @counter
への参照は、実際にClass
オブジェクトにインスタンス変数CleanerClass
を作成します。それを@@counter
に変更すると、あなたが好きなように思えるかもしれませんが、あなたが宣言したクラスだけでなく、他のクラスも汚染されます。
私はJavaに精通していませんが、[this](http://stackoverflow.com/a/2086837/4001311)答えが見つかりました。 –
アドバイス:あなたが知っている言語と学習している言語との類似点を探し出すことは致命的な結果に終わり、結果的に新しい言語の非慣習的で醜いコードになることがあります。私はむしろ特定の問題に焦点を当て、どのようにそれらをさまざまな言語で扱うかを考えます。 Javaの静的変数で通常解決される1つの問題を選択し、Rubyで正しい解決方法を尋ねます。答えはクラス変数かもしれませんが、しばしば無関係なものになることがよくあります。 –
いいえ、私は同じような直感を持っていたので、私はあなたを感じます。 – Casey