I坐标

博客园 首页 新随笔 联系 订阅 管理
User Defined Types用户定义类型

        除了Slice提供的基本类型以外,Slice还允许你自定义复合类型:枚举、结构、序列和词典。



枚举



        Slice的枚举定义看起来就像C++的枚举定义一样:



enum Fruit { Apple, Pear, Orange };



        上面的代码定义了一个名为Fruit的类型,Fruit是一种拥有自己权利的新的类型。Slice没有定义如何给枚举赋顺序值,但是Slice保证枚举的顺序值从左向右递增。



        不同于C++,Slice不允许你控制枚举的顺序值,例如下面的代码是错误的:



enum Fruit { Apple = 0, Pear = 7, Orange = 2 };



        实际上,只要你不在地址空间之间传递枚举的顺序值,那么你就不关心枚举的值是多少。例如,客户端向服务器发送了一个0值,用来表示Apple,这样就会引起问题,因为服务器可能不使用0值来表示Apple。但是,如果直接向服务器发送Apple,如果Apple在被接受的地址空间中使用一个不同的值表示,那么那个值会被Ice运行时正确的对应到Apple。



        Slice不允许定义空的枚举。同时,Slice的枚举会进入封闭的命名空间,如下的代码是错误的:



enum Fruit { Apple, Pear, Orange };



enum ComputerBrands { Apple, IBM, Sun, HP };



        上面的代码中Apple被二次定义了。



结构



        Slice支持容纳一个或多个任意类型的有名称得成员的结构,包括了用户自定义的复合类型,例如:





struct Time Of Day {
        
short hour;
        
short minute;
        
short second;

}


        上面的代码定义了名为TimeOfDay的新类型。结构定义形成了一个命名空间,因此结构中的成员的命名需要保持唯一性。



        结构中不能出现结构定义,例如下面的代码是错误的:





struct TwoPoints
{
        
struct Point
        
{
                
short x;
                
short y;
        }
;
        Point coord1;
        Point coord2;
}
;


        这条规则在Slice中的通用描述就是:除了模块,类型不能嵌套定义。这样做可以避免不同语言的不同的定义要求造成的冲突。所以,为了能够定义上面代码中的类型,你可以把两个结构分开定义。



序列



        序列是不定长度的元素向量。如下:



sequence<Fruit> FruitPlatter;



        一个序列是可以为空的,也就是说,序列可以不容纳元素,或者序列可以容纳在内存容量允许的范围之内的任意数量的元素,



        序列的元素也可以是序列,就是说,你可以创建下面的序列:



sequence<FruitPlatter> FruitBanquet;



        序列用来构造多种集合,例如向量、列表、队列、集合、包或者树。



        一个特殊的序列的用法已经变成了惯用的方法,即使用序列来提供可选的值。例如,我们可能有一个Part结构来记录装配到汽车的零件的详细信息,这个结构可以记录如零件的名称,描述,重量,价格和其他的信息等。备用零件通常有一个序列号,我们是噢有那个long类型的值来表示。实际上,一些零件,例如螺丝,我们通常没有螺丝的序列号,所以我们在螺丝的序列号李存放什么内容呢?下面有一些处理的选择:



  • 使用一个标记值(例如0)来指出没有序列号的情况。这个方法通常是可以正常工作的,只要所提供的标记值有效。似乎没有人会使用0来作为一个零件的序列号。但是,对于其他的一些值,例如温度,0就是一个不能作为标记值的值。
  • 将序列号的类型从Long改为string。string有自己的标记值,即空串。所以我们可以使用一个空串来指出没有序列号的情况。这样也是有效的,但是却违背了一个原则:我们不应该为了得到一个标记值而改变事物表示自身的自然的方法。
  • 增加一个标示位用来标示序列号是否有效,例如:



struct Part {
        
string name;
        
string description;
        
//
        bool serialIsValid;
        
long serialNumber;
}
;


        这样做可能会给我们带来另一个麻烦:迟早会有人因为忘了判断serialIsValid的值而直接使用serialNumber。



  • 使用一个序列来建立可选的字段。例如:



sequence<long> SerialOpt;

struct Part{

        
string name; 
        
string description; 
        
//
        SerialOpt serialNumber;

}



        通常,Opt后缀表明这个一个可选的元素。如果序列是空的,那么很显然没有序号,如果序列有一个值,那么那个值就是序列号。很明显,这样做有一个缺点,那就是有人会故意放多个值到序列中。这个做法可以通过加入一个特殊通途的Slice结构来解决。实际上,可选值很少使用,没有必要加入一种特定的语言特征来解决。



字典



        字典是键、值类型的映射。例如:



 



struct Employee {

        
long number;
        
string firstName;
        
string lastName;

}
;

dictionary
<long, Employee> EmployeeMap;

 



        上面的定义创建了一个名为EmployeeMap的字典,它达到了从employee编号到一个包含有employee详细信息的结构的映射。



        字典能够用来实现稀疏数组,或者任何使用非整数键值类型的用于查找的数据结构。尽管可以同uo设置一个包含了键值对的结构的序列也能用来构造类似的事情。但是字典更适合:



  • 字典清楚地表达了设计者的意图,即提供了一个从值的域到值的范围的映射。
  • 在编程语言级别上,序列被用向量的形式实现,也就说,序列不适合构建稀疏的域,而且,如果要定位一个元素需要线形的查找。换句话说,字典作为支持有效的查找的数据结构实现,其效率可以是:O(log n)甚至更好。
        字典的键值不一定要是整形,它可以是下面的数据类型的任何一种:
  • 整形(byte,short,int,long,bool以及枚举类型)
  • string
  • 使用整形或string作为元素的序列
  • 只容纳有整形或string类型的成员的结构

常量定义和直接量



        Slice允许你定义常量。常量定义必须是下面的类型中的一种:



  • 整形(bool, byte, short, int, long或者枚举)
  • float 或 double
  • string

        定义常量的语法与C plus plus和Java类似(有一点小的不同):



  • 布尔类型只能用关键字false和true初始化
  • 与C plus plus一样,整数类型可以用decimal,octal或二进制初始化。但是需要注意的是,如果你认为byte是数字而不是位模式,那么你可能在不同的实现语言中得到不同的结果。例如,在C plus plus中,byte映射到char,而对于不同的平台,char可能是有符号的或无符号的。注意,在C plus plus中使用的long和无符号常量的后缀(l,L,u,U)在Slice中是不合法的。
  • 浮点直接量定义使用C plus plus的语法,但是你不能使用l或者L后缀来定义扩展的浮点常量。而f和F是合法的。
  • String直接量定义支持 C plus plus的转义序列。与C plus plus相同,Slice把相邻的字符串直接量连接起来。
posted on 2005-01-28 17:08  I坐标  阅读(1476)  评论(0编辑  收藏  举报