使用變量時,除了以某標識符作為變量的名稱外,還要指定該變量的數(shù)據(jù)類型。一個數(shù)據(jù)類型定義了變量可接受的值以及所能執(zhí)行的操作。比如說,一個數(shù)據(jù)類型為 Age 的變量 Bill,Age 的取值范圍為 1..100,并只有 + – 這兩種操作,在這里,對象(object)為名為 Bill 的變量,它的取值在 1..100 之間(包括 1,100),值的變化只能通過+ -這些基本運算符(primitive operation)來實現(xiàn),而無法通過* /等其它運算符。Ada 中的數(shù)據(jù)類型,包括預定義類型,都是按照一定的格式在程序包中創(chuàng)建的。下面就介紹創(chuàng)建數(shù)據(jù)類型的一些基本內容,更多相關內容會在以后見到。
創(chuàng)建一個新類型,需要使用保留字 type,is,range。格式如下:
type type_name is range range_specifcation;
type_name 為新類型的名稱,是一個合法標識符;range_specifcation 表示該類型的取值范圍,表示方式為 First .. Last,如 1..100 , -9 ..10 。
例如創(chuàng)建上面提及的一個新類型 Age :
type Age is range 1 .. 100;
這樣就有了一個數(shù)據(jù)類型 Age, 取值范圍 1 .. 100。
有一點要注意:range_specfication 中 First 要大于 Last。 如 type months is range12 .. 0, 實際上 months 是一個空集(null),而不是所期望的 0..12。
不同數(shù)據(jù)類型之間是不能進行混合運算的,即使取值范圍和運算符一樣,看以下的程序例子:
000 — putwage.adb
001 with Ada.Text_IO; use Ada.Text_IO;
002 with Ada.Integer_Text_IO; use Ada.Integer_Text_IO;
003 procedure putwage is
004 subtype Age is Integer range 1 .. 100;
005 subtype Wage is Integer;
006 Bill_Age : Age := 56;
007 Bill_Wage: Wage := 56;
008 begin 009 Put (―Total wage is‖);
009 Put (Bill_Wage * Bill_Age);
010 New_Line;
011 end putwage;
[001]-[002]: 使用軟件包 Ada.Text_IO,Ada.Integer_Text_IO;兩個軟件包分別處理字符類輸出和整數(shù)輸出。
[003] [008] [012] 定義一個過程 putwage。 [004]-[005]: 定義新的數(shù)據(jù)類型Age,Wage,它們取值范圍都為 1..100。
[006]-[007]: 聲明兩個變量 Bill_Age,Bill_Wage,類型分別為 Age 和Wage, 并賦予相同初始值56。
[009]-[011]:依次輸出字符串‖Total wage is‖,整數(shù) Bill_Wage和Bill_Age的乘積,和一個新行符(EOL)。
以上程序看上去毫無問題,但根本無法編譯通過。首先,沒有定義類型Age和wage的 * 操作,因此Bill_Age和Bill_Wage無法相乘;第二,兩者數(shù)據(jù)類型不同,即使定義了*操作,還是無法相乘。 當然也可使用后面提到的類型轉換 ,如果將[010]改為Put (Integer(Bill_wage) * Integer(Bill_Age)),將會輸出所要的 3136;但如果改成Put (Integer(Bill_wage * 56)),看上去也行的通,但實際結果卻不是3136。不同數(shù)據(jù)之間不能進行運算,要牢牢記住。(Integer 是預先定義的一個整型,Integer(Bill_Wage)是將Bill_Wage強制轉換為整型)。
大家可能會發(fā)現(xiàn),如果像上面一樣創(chuàng)建一個截然不同的新類型,還需要定義它的運算符,使用很不方便。因此,往往是派生現(xiàn)有的類型,其格式為:
type type_name is new old_type {range range_specification};
type_name 為新類型的名稱,是一個合法標識符;range range_specification 表示該類型的取值范圍,是可選的,沒有的話表示新類型 type_name 的取值范圍和 old_type 一樣。如將上例改為:
000 — filename:putwage.adb
001 with Ada.Text_IO; use Ada.Text_IO;
002 with Ada.Integer_Text_IO; use Ada.Integer_Text_IO;
003 procedure putwage is
004 type Age is new Integer range 1 .. 100;
005 type wage is new Integer;
006 Bill_Age : Age := 56;
007 Bill_Wage: Wage := 56;
008 begin
009 Put (―Total wage is‖);
010 Put (Bill_Wage * Bill_Age);
011 New_Line;
012 end putwage;
上例還是不能編譯通過,因為派生類型只繼承母類型的屬性,如運算符,不同的派生類型即使母類型相同也還是屬于不相同的類型。但將[10]改為Put (Integer(Bill_wage * 56))則能輸出正確的結果。但是派生類型使用還是麻煩了一點,不同類型之間即使都是數(shù)字類型也無法混合使用,只是自己不用創(chuàng)建運算符省力了點。
創(chuàng)建新類型和派生類型的麻煩從上文就可以感受的到,特別是在科學計算這些有很多種小類型的軟件當中,上述兩種方法實在過于繁雜。這時子類型(subtype)就相當有用,子類型的定義格式為:
subtype type_name is old_type {range range_specification};
type_name 為新類型的名稱,是一個合法標識符;range range_specification 表示該類型的取值范圍,是可選的,沒有的話表示新類型 type_name 的取值范圍和 old_type 一樣。
再將先前的例子改一下:
000 — putwage.adb
001 with Ada.Text_IO; use Ada.Text_IO;
002 with Ada.Integer_Text_IO; use Ada.Integer_Text_IO;
003 procedure putwage is
004 subtype Age is Integer range 1 .. 100;
005 subtype Wage is Integer;
006 Bill_Age : Age := 56;
007 Bill_Wage: Wage := 56;
008 begin 009 Put (―Total wage is‖);
009 Put (Bill_Wage * Bill_Age);
010 New_Line;
011 end putwage;
編譯通過,輸出值為3136。子類型不僅繼承母類型的屬性,而且和母類型、其它同母類型的子類型可混合使用。
在前面的例子中的,我們都提到了取值范圍,這也是 Ada 的一項―特色‖:Ada 不同于 C 和 Pascal— 賦給一個變量超過其取值范圍的值或進行不合法運算,會輸出錯誤的值而不報錯,與此相反,Ada 程序在編譯時會提示錯誤,或在運行 Ada 程序時產生Constraint_Error異常(異常和 C 中的信號Signal差不多。
更多建議: