簡體   English   中英

Ruby類變量是否與Java靜態變量類似?

[英]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的引用實際上在定義CleanerClassClass對象上創建了一個實例變量。 將它更改為@@counter ,因為它看起來像你應該的那樣,會污染其他類,除了你聲明它的那個類。

暫無
暫無

聲明:本站的技術帖子網頁,遵循CC BY-SA 4.0協議,如果您需要轉載,請注明本站網址或者原文地址。任何問題請咨詢:yoyou2525@163.com.

 
粵ICP備18138465號  © 2020-2024 STACKOOM.COM