type dept=(house,sports,drugs,food,liquor);
month=1..12;
item=record
price:real;
case available:boolean of
true:(amount:integer;
where:dept);
false:(month_expected:month)
end;
var i1,i2:item,
……
i1.price:=5.24;
i1.available:=true;
i1.amount:=29;
i1.where:=liquor;
i2.price:=324.99;
i2.available:=false;
i2.month_expect:=8;
price
available
amount
where
5.24
true
29
liquor
price
available
month_expected
324.99
false
8
二, 组合类型
1,数组
① 约束数组类型
? 下标界是静态确定的
type MONTH is (JAN,FEB,MAR,APR,MAY,JUN,
JUL,AUG,SEP,OCT,NOV,DEC);
type YEARLY_PAY is array(MONTH) of INTEGER;
type SUMMER_PAY is array(MONTH range JUL..SEP) of INTEGER;
② 非约束数组类型
? Ada支持动态数组
type SOME_PERIOD_PAY ia array(MONTH
range< >) of INTEGER;
type INT_VERTOR ia array(INTEGER range < >)
of INTEGER;
type BOOL_MAXTRIX is array(INTEGER range < >,
INTEGER range < >) of BOOLEAN;
③ Ada数组类型由分量的类型,下标个
数和下标类型来刻画
④ 界的确定可在数据对象成为实体时,
或参数传递时完成
SPRING_MONTH:SOME_PERIOD_PAY(APR..JUN);
Z:INT_VECTOR(-100..100);
W:INT_VERTOR(20..40);
Y:BOOL_MAXTRIX(0..N,0..M);
其中,界的值不一定静态给出
function SUM(X:INT_VECTOR) return INTEGER;
RESULT,INTEGER:=0;
begin
for I in X’FIRST..X’LAST loop
RESULT:= RESULT+X(I);
end loop;
return RESULT;
end SUM;
可用不同大小的数组作为实参来调用该函数
如, A:=SUM(Z)+SUM(W);
⑤ 可以在过程的局部说明中说明一个
数组,它的界依赖于一个参数
TEMPORARY:INT_VECTOR(X’FIRST..X’LAST);
⑥ 切片,用以选取一维数组若干个相
继分量
LINE:STRING(1..80);
LINE(1..11):=(‘D’,’e’,’a’,’r’,’’,’f’,’r’,’i’,’e’,’n’,’d’);
2,记录
① 说明形式
type COORDINATE is
record
X:INTEGER range 0..100;
Y:CHARACTER;
end record;
② Ada的判全或是安全的
type DEPT is (HOUSEWARE,SPORTS,
DRUGS,FOOD,LIQUOR);
type MONTH is range 1..12;
type ITEM (AVAILABLE:BOOLEAN,=TRUE) is
record
PRICE:REAL;
case AVAILABLE of
when TRUE=>AMOUNT:INTEGER;
WHERE:DEPT;
when FALSE=>MONTH_EXPECTED:MONTH
end case;
end record;
判定或可具有缺省初值
也可以说明一个对象的变体是冻结的
单独对判定或赋值是不允许的
PEACH:ITEM;
ORANGE:ITEM(FALSE);
COCA_COLA:ITEM;
COCA_COAL:=ORANGE; (合法 )
COCA_COAL:=(PRICE=>1.99,AVAILABLE=>TRUE,
AMOUNT=>1500,WHERE=>FOOD);
3.访问类型
① 不完全类型说明
应用于 Ada的递归类型
type BINARY_TREE_NODE;
type TREE_REF is access BINARY_TREE_NODE;
type BINARY_TREE_NODE is
record
INFO:CHARACTER;
LEFT,RIGHT:TREE_REF;
end;
② P.all代表整个结点
4.子类型和派生类型
①可以通过子类型来规定类型的一个特性
type FLAVOR is (CHOCOLATE,MINT,PEATH,STRAWBERRY,
VANILLA,BLUECHEESE,CATSUP,GARLIC,ONION);
subtype ICE_CREAM_FLAVOR is range CHOCOLATE.,VANILLA;
subtype SMALL_INT is INTEGER range -10..10;
subtype SMALL_POS_INTEGER is INTEGER range 1..10;
subtype MY_INT_SET is INTEGER range A..B;
② 子类型继承基类型的所有特性,还满足某个约束
③ 子类型机制也可以用来约束数组类型
(类似于给出实例 )
type MY_ORDERS is array(INTEGER range< >)
of ICE_CREAM_FLAVOR;
subtype MONTHLY_ORDERS is MY_ORDERS(1..31);
subtype ANNUAL_ORDERS is MY_ORDERS(1..365);
④ 也可以使用子类型来冻结判定或类型的变量
subtype OUT_OF_STOCK is ITEM(FALSE);
⑤ 子类型机制并未定义新类型
⑥ 派生类型定义新类型,这些新类型继承了
母体类型的所有特性
type <新类型 > is new <母体类型 > [<约束 >]
type POSITIVE is 1..INTEGER’LAST;
type WEIGHT is new POSITIVE range 1..100;
type LENGTH is new POSITIVE;
5.属性
Ada 的属性用来指定数据对象, 类型的
特性 。
如,INTEGER’LAST
三, Ada数据类型小结
Ada类型
标量类型 组合类型 访问类型
(递归 )
数值类型 枚举类型 数组类型 记录类型
预定义类型 用户定义类型 预定义类型 用户定义类型
整型 字符型
实型 布尔型
第六节 类型检查
1,类型检查
对数据对象的类型和使用的操作是否匹
配的一致性检查称为 类型检查
2,静态检查和动态检查
① 静态检查使程序更正确更有效
② 动态检查使编程方便,但影响了可读
性,且降低了执行效率
3.强类型语言
若一个语言允许 所有 的类型静态检查
4,Pascal是非强类型语言
① 编译时,不能确定一个过程中的过程参
数和子程序参数类型
procedure who_knows(i,j:integer;procedure f);
var k:boolean;
begin k:=j<i;
if k then f(k) else f(j)
end;
② Pascal的子界不能静态检查
如, a:=b+c;
且 a,b,c均属于子界类型 1..10
③ 变体记录的标识符可以在运行时改

④ Pascal没有严格规定类型的一致性
规则
第七节 类型转换
1,语言应该提供类型转换机制
如 A+B
2.两种转换方式
① 拓展,整型 → 实型
② 收缩,实型 → 整型
有的, 截断,,有的, 四舍五入,
3,注意语言规定的转换规则
① Fortran:低级类型 → 高级类型
② Pascal允许,整数 → 实数 ;实数 → 整数 显式
转换 (frunc,round)
③ ALGOL 68提供了六种强制转换规则 (隐
式的 )
④ Ada要求必须显式转换
例如, 派生类型到母体类型的转换
P是 POSITIVE的变量, L是 LENGTH的变量
P:=POSITIVE(2*L+35);
第八节 类型等价
? T1和 T2是相容的,T1可赋给 T2,T1可对应 T2
的形参;反之亦然。
1,名字等价
两个变量的类型名相同。
2,结构等价
两个变量的类型具有相同的结构。
验证法,用用户定义类型的定义来代替用户定
义名,重复这一过程,直到没有用户
定义类型名为止。
3,两种相容性实现时的比较
①名字等价的实现比较简单
②结构等价的实现需要的模式匹配过程可能十
分复杂
第九节 抽象数据类型
1,用户定义类型与内部类型的异同
① 都建立某种基本表示的抽象
如,integer是位串的抽象 ;
reg_polygon是记录的抽象
② 每一类型都关联一组操作
③ 内部类型隐蔽了基本表示, 不能对
它的成分进行操作 ;用户定义类型具
有更高级别的抽象, 可以对其基本
表示的成分进行操作 。
2,抽象数据类型的定义
满足下述特性的用户定义类型称为 抽
象数据类型,
① 在实现该类型的程序单元中,建立
与表示有关的基本操作 ;
② 对使用该类型的程序单元来说,该类
型的表示是隐蔽的 。
一, SIMULA 67的类机制
1.类的说明
<类头 >;<类体 >
<类头 >包括类名和形式参数
<类体 >是传统的分程序,可包含变量, 过程
和类的局部说明, 以及一些执行语句
例:复数表示 (幅角,半径 )
class complex( x,y); real x,y;
begin real angle,radius;
radius,=sqrt( x**2+y**2);
if abs( x) <epsilon
then begin if abs(y)<epsilon
then error
else begin if y>epsilon
then angle:=pi/2
else angle:=3*pi/2
end
end
else angle:=arctan(y/x)
end complex
2,类的有关性质
① 类说明定义了一类数据对象的原型
或样板
② 类的每个实例是一个可操作的数据
对象
③ 类的实例可多次动态建立,且仅能通
过指针引用
例, ref(complex) c;
c:- new complex(1.0,1.0);
c
0.78
1.42
1.0
1.0
angle
radius
x
y
④ 类实例的属性是指类体的 局部变量
和类头中的 参数
my_angle:=c.angle;
my_radius:=c.radius;
my_x:=c.x;
my_y:=c.y;
⑤ 类支持抽象数据类型的封装机制,它
可以封装实现对数据操作的各种过程
例, 可将复数加和乘的过程 add和 multiply封
装入类 complex的类体说明中,作为
complex的属性。
procedure add(operand);ref (complex) operand
procedure multiply(operand);ref (complex) operand
变量 c1,c2引用的两个复数相加可表示为:
c1.add(c2)
3,子类
用以定义类型的判断或和类属 。
要求:定义一个栈, 完成
?引用栈顶元素
?入栈
?出栈
?判栈是否空
(这些操作与栈中元素的类型无关 )
栈内成员的元素类
class stack_member;
begin ref (stack_member) next_member;
next_member:-none
end
指针型局部变量
class stack;
begin ref (stack_member) first;
ref (stack_member) procedure top;
top:-first;
procedure pop;
if ?empty then first:-first.next_member;
procedure push(e);ref (stack_member) e;
begin if first =/=none
then e.next_member:-first;
first:-e
end push;
boolean procedure empty;
empty:=first= =none;
first:-none
end stack
stack_member class complex(……);
……
end complex
定义了一个复数栈
其中 complex称为 stack_member的子类
加在类说明之前
① 子类 complex具有自己的属性,同时
继承了 stack_member的属性
new complex
产生的对象具有 stack_member和 complex的
所有属性
ref(stack) s;
s:-new stack;
s.push(c1);
s.push(c2);
s.push(c3);
建立一个复数栈
② 具有 ref(stack_member)的变量可引用
多种类型的量,但不同类型的元素不得压
入同一栈实例中
下述语句说明向量也可是栈中元素,
stack_member class vector(…);
……
end vector