1. 程式人生 > >寶書課程#1:Ada 2005中的受限型別 --受限集合

寶書課程#1:Ada 2005中的受限型別 --受限集合

寶書課程#1:Ada 2005中的受限型別

--受限集合

by Bob Duff—AdaCore

Translator:Dongfeng.Gu

讓我們開始吧

一個Ada我所喜歡的特徵是對於集合的“全覆蓋規則”。例如,假設我們有一個記錄型別:

   type Person is

      record

         Name : Unbounded_String;

         Age : Years;

      end record;

我們可以使用一個集合來建立一個這個型別的物件:

   X : constant Person :=

      (Name => To_Unbounded_String (”John Doe”),

       Age => 25);

全覆蓋規則意思是所有的Person的成員必須在集合中記錄。如果我們接著通過增加一個成員來修改Person型別:

   type Person is

      record

         Name : Unbounded_String;

         Age : Natural;

         Shoe_Size : Positive;

      end record;

我們忘記修改X,於是編譯器將提醒我們。Case語句也同樣有全覆蓋規則,它提供一個近似的目的。

當然,我們可以通過使用“others”來擊敗全覆蓋規則(通常用於陣列集合與情形語句,也偶爾對記錄集合有用):

   X : constant Person :=

      (Name => To_Unbounded_String (”John Doe”),

       others => 25);

根據Ada參考手冊,“others”這裡精確的表示“Age|Shoe_Size”。但那是錯誤的:“others”真實的含義是“其它所有成員,包含我們可能在下週或下年將新增的成員”。這意味著你不應該使用“others”,除非你非常確信它將適用於所有未創作的情形。

到目前為止,這都是舊新聞了--自從Ada83以來全覆蓋規則一直被維護。這和Ada2005有什麼關係呢?

假設我們有一個受限型別:

   type Limited_Person is limited

      record

         Self : Limited_Person_Access := Limited_Person'Unchecked_Access;

         Name : Unbounded_String;

         Age : Natural;

         Shoe_Size : Positive;

      end record;

這個型別有一個自引用,它對複製物件沒有意義,因為Self將最後指向錯誤的地方。因此,我們希望使型別受限,來防止程式設計師意外地建立副本。總之,該型別可能是私有的,因此客戶端程式設計師可能不會意識到這個問題。我們也可以通過受控型別來解決那個問題,但是受控型別是費開銷的,並且會增加不必要的複雜度,如果沒有必要的話,就不要使用受控型別。

Ada95中,對於受限型別的集合(宣告)是非法的。因此,我們將面臨一個艱難的選擇:建立受限型別物件,並且像這樣初始化它:

   X : Limited_Person;

   X.Name := To_Unbounded_String ("John Doe");

   X.Age := 25;

這裡有一個全覆蓋規則應該防止的維護問題。或許,使型別非受限,這樣可以獲得集合(宣告)的福利,但卻失去防止拷貝的能力。

Ada2005中,一個集合(宣告)可以用於受限物件。我們可以說:

   X : aliased Limited_Person :=

      (Self => null, – Wrong!

       Name => To_Unbounded_String (”John Doe”),

       Age => 25,

       Shoe_Size => 10);

   X.Self := X'Access;

我們將在未來的寶書課程中看到“Self=>null”做了什麼。

一個非常重要的要求需要指出:建立X的值必須現場實現,不可以在一個臨時變數中建立一個集合宣告,然後複製它到X,因為這將違反受限物件的整個出發點--你不可以複製它們。