[英]Are Ruby class variables similar to the Java static variables?
我正在從Java過渡到Ruby並嘗試理解Ruby作用域。
似乎類變量的行為與Java中的靜態變量相同。 這種解釋是否正確? 如果是這樣,那么Ruby全局變量是否等同於Java中的公共靜態變量?
我不熟悉java,但我可以用Ruby術語解釋。
在Ruby中,類變量在變量名之前有@@
。 它的行為並不像您認為的那樣。 創建類變量后,它將在所有子類之間共享。 它不僅限於您創建它的類。
至於全局變量,它在變量名之前有$
。 它完全像它聽起來那樣,它是全球性的,可以在任何地方訪問。
Ruby中不建議使用這兩個變量。 您可以使用實例變量來執行所需操作,該變量在名稱前面具有@
。 它是特定於對象的。 如果在一個對象中聲明它,它將不會顯示在另一個對象中。
我希望這可以解決這個問題。
Ruby和Java之間存在很多相似之處,因為它們是面向對象的,但它們的族譜是不同的。 Ruby非常依賴Smalltalk而Java繼承自C ++思想流派。
這里的區別在於Ruby的公共/私有/受保護的概念要弱得多,它們比規則更多的建議,而靜態方法或常量之類的東西更像是一種模式,而不是語言中的構造。
全局變量相當不受歡迎,如果大量使用它們會導致混亂。 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.
即使像這個模塊這樣的薄層也能讓你從這個變量中截取讀/寫操作並改變行為。 也許您希望默認為特定值或將值轉換為規范化形式。 在全球范圍內,您必須在任何地方重復此代碼。 在這里你可以鞏固它。
類變量是完全不同的東西。 它們也是最好避免的,因為在類和類的實例之間共享數據可能會很混亂。 它們是兩種不同的背景,應該尊重分離。
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中並非如此。 您必須編寫橋接/代理/委托方法,這里的術語取決於您習慣使用的內容。
一個重要的區別是類方法和實例變量在Ruby中以靜態方法和實例變量不能在Java中交互的方式。
tadman的回答包含以下代碼:
class CleanerClass
def self.counter
@counter ||= 0
end
def self.counter=(v)
@counter = v.to_i
end
end
對於世界上的Java(和C#)程序員來說,這段代碼看起來應該不起作用。 畢竟,在該模型中,從靜態方法訪問實例變量的想法是不連貫的(甚至不會編譯)。 重點是你還沒有實例!
但是,在Ruby中,每個類定義本身都是Class
類型的一個實例。 對@counter
的引用實際上在定義CleanerClass
的Class
對象上創建了一個實例變量。 將它更改為@@counter
,因為它看起來像你應該的那樣,會污染其他類,除了你聲明它的那個類。
聲明:本站的技術帖子網頁,遵循CC BY-SA 4.0協議,如果您需要轉載,請注明本站網址或者原文地址。任何問題請咨詢:yoyou2525@163.com.