Ruby 註解

2006 年 10 月 26 日

Ruby 最受歡迎的功能之一是支援 元程式設計,也就是像變更語言本身一樣運作的功能,例如引入新的關鍵字。

儘管主流的大括號語言普遍較不支援元程式設計,但它們有一個有用的功能,就是 註解。註解是語言增強 InternalDslStyle 的重要功能。乍看之下,Ruby 不支援註解,但如果你換個角度想,就會發現它確實支援。

使用註解時,你可以用標記標註語言元素(類別、方法、欄位等),這基本上就是關於該元素的元資料。然後你可以在執行時期或編譯時期使用該元資料。

一個很好的範例就是由 NUnit2 開創的測試標記。

[Test] public void SomeTestMethod() {...

在執行時期,NUnit 架構會檢視類別,找出註解為 [Test] 的方法,然後執行這些方法。

註解可以帶參數。因此,如果你懷念 Pascal 的子範圍,它允許你指出變數的有效範圍,你可以用類似下列的方式定義它們

  
@ValidRange(lower = 1, upper = 1000)
  private int weight; // in lb
  @ValidRange(lower = 1, upper = 120)
  private int height; // in inches

這與 Pascal 的子範圍概念不太一樣,它只定義有效範圍,你仍然必須建構機制來檢查值,例如呼叫物件上的 isValid 方法(我同意這不太像 ContextualValidation)。但重點是,你已經定義了關於該變數自己的宣告式陳述。

那麼,在 Ruby 中如何執行此操作?類似這樣

	validate_range :@height, :with => 1..120
	validate_range :@weight, :with => 1..1000

在語法方面,最大的差別在於使用 Java(或 .NET)註解時,您會將註解置於要註解的元素之前。在 Ruby 中,您會在註解中命名要註解的元素。儘管這會增加一些輸入(對於 Ruby 來說,這是一個罕見的陳述),但它確實讓您可以在類別中的任何位置放置註解。它也讓建立參照多個語言元素的註解變得更簡單。

這兩種樣式之間更深層的差別在於它們的實作方式。大括號註解是一種特殊的語言結構,它將特殊物件作為元資料附加到語言元素。這些註解物件可以在編譯時期(使用 Java 的 apt)或執行時期進行查詢和處理。

另一方面,Ruby 的註解通常是在超類別或包含的模組中定義的類別方法。透過直接在類別定義中撰寫這些註解,它們會在載入類別時執行。因此,它們不是特定的語言功能,而是使用類別方法的一種方式。您不必建立元資料物件(儘管您可以在需要時建立),您更有可能只建立物件來執行您希望它們執行的任務。

由於 Ruby 的動態特性,您可以使用註解執行更多有趣的事情。特別是,您可以執行程式碼產生。最明顯的範例是類似於 attr_accessor :height 的內容,它會為欄位產生取得和設定方法,有效地修改類別本身。使用 apt,Java 可以執行一些類似的事情,但您無法修改類別本身。使用建置指令碼和部分類別,您可能可以在 C# 中執行類似的事情,但這種執行時期程式碼產生在 Ruby 中肯定更自然,這是它類似 Lisp 的元素之一。

Rubyist 沒有將這些東西稱為註解。我喜歡做的事情之一是找到跨語言的常見技術,對我來說,這是一種常見技術,而「註解」似乎是一個很好的通用詞。我不知道 Rubyist 是否會同意。