第13章编译单元.ppt

上传人:本田雅阁 文档编号:3125372 上传时间:2019-07-13 格式:PPT 页数:85 大小:300.52KB
返回 下载 相关 举报
第13章编译单元.ppt_第1页
第1页 / 共85页
第13章编译单元.ppt_第2页
第2页 / 共85页
第13章编译单元.ppt_第3页
第3页 / 共85页
第13章编译单元.ppt_第4页
第4页 / 共85页
第13章编译单元.ppt_第5页
第5页 / 共85页
点击查看更多>>
资源描述

《第13章编译单元.ppt》由会员分享,可在线阅读,更多相关《第13章编译单元.ppt(85页珍藏版)》请在三一文库上搜索。

1、2004.11.3,AI程序设计,1,第13章 编译单元,本章介绍Visual Prolog编译单元的有关内容,包括接口、类声明、类实现、各种类型转换、条件编译、异常处理、预处理程序指令等。 一个程序由若干编译单元组成。编译器分别编译这些编译单元。编译的结果是一个个目标文件。这些目标文件(可能还有其它文件)连接在一起形成项目的目标文件。一个程序必须确实包含一个目标段,它是程序的入口点。 在一个单元中所有的引用名被声明或被定义的情况下,一个编译单元必须自包含。在几个编译单元中可以包括接口定义和类声明(定义或声明必须在包含它们的所有单元内一致)。 然而类实现(定义)只能在一个单独的单元中被定义。每

2、个被声明的项也必须在项目中被定义,但是一些项可以在程序库中定义,就是说它们不需要文本定义。,2004.11.3,AI程序设计,2,第13章 编译单元,一个编译单元(可能用#include指令构成)是编译数据项的序列。 compilationUnit : compilationItem-list-opt 一个编译数据项是一个接口、类声明、类实现、目标段,或者是在条件编译中所说的一个有条件的编译数据项。 compilationItem : conditionalItem interfaceDefinition classDeclaration classImplementation goalSec

3、tion,2004.11.3,AI程序设计,3,第13章 编译单元,13.1 接口 13.2 类声明 13.3 类实现 13.4 类型转换 13.5 条件编译 13.6 异常处理 13.7 预处理程序指令 本章小结 本章习题,2004.11.3,AI程序设计,4,本节介绍Visual Prolog的接口的有关概念,内容包括接口的基本概念、接口于对象、开放限定(Open Qualification)、支持限定(Support Qualification)等。,13.1 接口,2004.11.3,AI程序设计,5,13.1.1 接口的基本概念,一个接口定义定义了一个命名的对象类型。接口可以支持其它

4、接口。详细内容参见支持限定。 在接口中声明的所有谓词都是接口类型对象的对象成员。 接口也是一个全局作用域,在其中可以定义常量和论域。这样,在一个接口中被定义的常量和论域不是该接口指示的类型的一部分(或具有该类型的对象)。 这样的论域和常量可以通过限定接口名interface:constant或使用开放限定由其它作用域引用。,2004.11.3,AI程序设计,6,13.1.1 接口的基本概念,interfaceDeclaration : interface interfaceName scopeQualifications sections endinterface interfaceName-

5、opt interfaceName : lowerCaseIdentifier 在构造器尾部的接口名interfaceName(如果存在)必须与构造器开始的接口名interfaceName相同。,2004.11.3,AI程序设计,7,13.1.1 接口的基本概念,在构造器尾部的接口名interfaceName(如果存在)必须与构造器开始的接口名interfaceName相同。 作用域限定ScopeQualifications必须是下面的类型: 支持限定supportsQualification 开放限定openQualification 段sections必须是下面的类型: 常量段consta

6、ntsSection 论域段domainsSection 谓词段predicatesSection 接口谓词段predicatesFromInterface 条件段conditionalSection 所有包含在条件段的部分也必须是这些类型。,2004.11.3,AI程序设计,8,13.1.2 接口与对象,如果一个接口没有明确地支持任何接口,那么它就隐含地支持内部接口对象。 对象是一个空接口,即它不包含谓词等内容。 对象的目的是作为所有对象的通用基本类型。,2004.11.3,AI程序设计,9,13.1.3 开放限定,开放限定(Open Qualification)可以更方便地引用类层次的实体

7、。开放段把一个作用域名代入另一作用域,以使这些名字可以在不受限制的情况下被引用。 开放对于对象成员的名字没有影响,因为无论如何它们只能被一个对象访问。但是类成员名、论域、算符和常量可以不受限制地被访问。 当名字以这样的方式被带进一个作用域时,可能会出现有些名字变得不明确。 开放段只会在它们所出现的作用域内产生影响。尤其是指,在一个类声明中的开放段不会影响类实现。 openQualification : open scopeName-comma-sep-list,2004.11.3,AI程序设计,10,13.1.4 支持限定,支持限定(Supports Qualification)只能在接口定义

8、interfaceDefinition 和类实现classImplementation中使用。 支持限定用于以下两种情况: 指定一个接口A扩展到另外一个接口B,因此,对象类型A是对象类型 B的子类型。 声明一个特定类的对象“私下”具有比一个指定作为构造类型的类更多的对象类型。 支持存在一个传递关系:如果接口A支持接口B,并且接口B支持接口C,那接口A也支持接口C。 如果一个接口没有明确支持任何接口,那么就暗指它支持预定义的接口对象。 当支持用于一个类的实现中时,结果是“This“不但可以与构造类型一起使用,而且还能与任何私有的所支持的对象类型一起使用。,2004.11.3,AI程序设计,11,

9、13.1.4 支持限定,supportsQualification : supports interfaceName-comma-sep-list 支持限定supportsQualification 只能在接口定义interfaceDefinition 和类实现 classImplementation中使用。 注意,如果接口有冲突的谓词,则它们就不能在一个支持限定内一起使用。 如果谓词具有相同的名字和变元数,具有不同的原始接口,那就是冲突的。 一个谓词的原始接口是该谓词文字上被声明的谓词的接口,同时它反对由支持限定间接声明的接口。因此如果同一接口在支持链中出现两次或更多次,它也不会发生冲突。,

10、2004.11.3,AI程序设计,12,13.1.4 支持限定,举例 考虑下面的接口: interface aaa predicates insert : (integer X) procedure (i). end interface interface bbb predicates insert : (integer X) procedure (i). end interface interface cc supports aaa, bbb % conflicting interfaces end interface,接口cc是非法的,因为在aaa中所支持的insert/1以aaa为源,而

11、在bbb中所支持的insert/1则是以bbb为源的。,2004.11.3,AI程序设计,13,13.2 类声明,一个类声明(Class Declarations)定义针对环境的类的外部特征:环境完 全可以看见和使用那些在类声明中提及的实体。我们说类的声明指定了类的公共 部分。 一个类声明可以包含常量和论域的定义,以及谓词的声明。 在类声明中所提到的一切都属于该类,而不属于它所构造的对象。与该对象 相关的一切,必须在该类所构造的对象的构造类型中被声明。 特别值得注意的是,一个类声明并不描述任何与代码继承有关的内容。代码 继承是一个完全私有的事件,它只能在类实现中被声明。(这不像其它的面向对 象

12、程序设计语言,它在实现中隐藏所有的细节),2004.11.3,AI程序设计,14,13.2 类声明,classDeclaration: class className constructionType-opt scopeQualifications sections end class className-opt constructionType : : interfaceName className : lowerCaseIdentifier 在类声明尾部的类名className(如果存在的话)必须与其头部的类名 className一致。 注意,可以使用与指定为该类的构造类型的接口名构造类型

13、 constructionType相同的类名className。写作: class interfaceAndClassName : interfaceAndClassName 注意,类和接口可以声明域和常量,并且由于它们在同名的空间内结束,所 以一定不会发生冲突(因为它们只能以相同的接口名或类名限定)。,2004.11.3,AI程序设计,15,13.2 类声明,作用域限定scopeQualifications 必须是 开放限定openQualification类的。 段sections必须是下面的几种: 常量段constantsSection 论域段domainsSection 谓词段pred

14、icatesSection 构造段constructorsSection 条件段conditionalSection 构造段constructorsSections只在该类声明为构造类型 constructionType时才是合法的。,2004.11.3,AI程序设计,16,13.3 类实现,本节介绍类实现(Class Implementations)的有关知识,包括类实现的基本概念、继承限定(Inherits Qualification)、归结限定(resolve qualification)、委托限定(Delegate Qualification)、This修饰、构造(Constructi

15、on)、终结(Finalization)等内容。,2004.11.3,AI程序设计,17,13.3.1 类实现的基本概念,类实现用于提供类声明中所声明的谓词的定义和构造器,以及它构造的对象所支持的任意谓词的定义。 类可以私有地(即在实现内部)声明和定义比类声明中提到的更多的实体。特别地,一个实现可以声明用于实现类和对象声明的事实数据库。 实现是一个混合作用域,在这个意义上来说,它包括了类的实现和类所产生的对象。类中的类部件在类的所有对象间共享,与对象部件相反,对象部件相对每个对象来说是单独的。类部件和对象部件都可以包含事实和谓词,而论域、算符和常量总是属于类部件,就是说它们不属于单个对象。,2

16、004.11.3,AI程序设计,18,13.3.1 类实现的基本概念,缺省时,类实现中声明的所有谓词和事实对象都是对象成员。为了声明对象成员,段关键字(即predicates 和 facts)前必须加上前缀class。所有在这样的段中声明的成员都是类成员。 类成员可以引用类的类部件,但是不能引用对象部件。 另一方面,对象成员既可以访问类的类部件,又可以访问对象部件。 在实现的代码中,所有对象谓词都包含宿主对象。所包含的宿主对象也可以直接通过特殊变量“This“来访问。 classImplementation : implement className scopeQualifications s

17、ections end implement className-opt 在类实现尾部的类名className(如果存在的话)必须与其头部的类名className一致。,2004.11.3,AI程序设计,19,13.3.1 类实现的基本概念,作用域限定ScopeQualifications必须是下面的几种: 支持限定supportsQualification 开放限定openQualification 继承限定inheritQualification 归结限定resolveQualification 委托限定delegateQualification 支持限定描述接口列表,这些接口由类实现私有地

18、给予支持。委托限定把接口谓词或对象的功能委托给对象谓词,它们可以作为事实变量被存储起来。,2004.11.3,AI程序设计,20,13.3.1 类实现的基本概念,段必须是以下几种: 常量段constantsSection 论域段domainsSection 谓词段predicatesSection 构造器段constructorsSection 事实段factsSection 子句段clausesSection 条件段conditionalSection 只有类的类名className声明了一个构造类型constructionType时,构造器段constructorsSections才是合法

19、的。声明了一个构造类型constructionType的那些类也是对象构造器,可以构造所声明的构造类型的对象。,2004.11.3,AI程序设计,21,13.3.1 类实现的基本概念,举例 下面这个例子说明了类事实怎样在类的对象中被共享,而对象事实不被共享。考虑接口aa和类aa_class: interface aa predicates setClassFact : (integer Value) procedure (i) . getClassFact : () - integer procedure () . setObjectFact : (integer Value) procedu

20、re (i) . getObjectFact : () - integer procedure () . end interface class aa_class : aa end class,2004.11.3,AI程序设计,22,谓词的指针是这样一种指针,它们可以从各个类和对象事实中存取其值: implement aa_class class facts classFact : integer := 0. facts objectFact : integer := 0. clauses setClassFact(Value) :- classFact := Value. getClassF

21、act() = classFact. clauses setObjectFact(Value) :- objectFact := Value. getObjectFact() = objectFact. end implement aa_class 假设这个类考虑目标goal: goal A1 = aa_class:new(), A2 = aa_class:new(), A1:setClassFact(1), A1:setObjectFact(2), ClassFact = A2:getClassFact(), ObjectFact = A2:getObjectFact().,类事实在所有的对

22、象中被共享,所以通过A1设置的类事实也会影响通过A2获得的值。因此,ClassFact的值只有一个,就是通过A1设置的值。 另一方面,对象事实属于每个对象。所以,在A1中设置的对象事实不会影响A2中存储的值。因此,ObjectFact的值是零,它是A2中初始化的事实值。,2004.11.3,AI程序设计,23,13.3.2 继承限定,继承限定用于声明一个实现对一个或多个类的继承。继承只影响类的对象部件。从其它类继承的目的是继承那些类的行为。 当类cc继承了类aa,那么类cc的对象将包含类aa的一个嵌入对象。 对象谓词可以被继承:如果类不执行它的某个对象谓词,但是它所继承的其中一个类执行了这些谓

23、词,那么这些谓词就将用于当前类。 从其他类继承的类对于继承类没有任何特权:它只能通过构造器类型接口访问所嵌入的对象。,2004.11.3,AI程序设计,24,13.3.2 继承限定,继承必须是明确的。如果类定义了谓词本身,那么不会出现含糊的问题,因为这个谓词定义是被显示表达的。如果只有一个继承类支持谓词,那么类所提供的定义也是明确的。但是如果两个或两个以上的类支持该谓词,那么类所提供的定义就是含糊的。在这种情况下,必须通过一个归结限定,使这种含糊性得到解决。(参见归结限定) 源自继承类的对象谓词可以从当前类的对象谓词直接调用,这是因为内嵌的子对象(sub-object)被隐含地用作谓词所有者。

24、类限定可以用于解决来自继承类对象谓词的调用模糊性。 inheritsQualification : inherits className-comma-sep-list,2004.11.3,AI程序设计,25,13.3.3 归结限定,正如其它地方讲过的那样,凡是与谓词调用有关的含糊问题,都可以通过使用限定名来避免。但是当涉及到继承问题时就不成立了。考察下面的例子: interface aa predicates p : () procedure () . . end interface class bb_class : aa end class class cc_class : aa end c

25、lass class dd_class : aa end class implement dd_class inherits bb_class, cc_class end implement,2004.11.3,AI程序设计,26,13.3.3 归结限定,在本例中,类bb_class 和类 cc_class哪一个向类dd_class提供aa 的实现是不确定的。(注意:当说到一个类实现一个接口时,就是指这个类向这个接口中声明的谓词提供定义。) 当然有可能向dd_class的实现添加子句,这将有效地解决这项工作。比如考虑下面的子句,它会从bb_class中输出谓词p: clauses p() :-

26、 bb_class:p(). 但是,用这一代码并没有真正继承bb的行为,实际上是向该类的bb_class部件委托了这项工作。,2004.11.3,AI程序设计,27,13.3.3 归结限定,要解决这种含糊性问题(并使用真正的继承而不是委托),使用一个归结 (resolve)段。归结段包含若干个解: resolveQualification : resolve resolution-comma-sep-list resolution : interfaceResolution predicateFromClassResolution predicateRenameResolution predi

27、cateExternallyResolution 归结限定用于从指定的源程序中确定实现。,2004.11.3,AI程序设计,28,13.3.3 归结限定,谓词归结 predicateFromClassResolution : predicateNameWithArity from className 一个来自类归结(class resolution)的谓词,声明该谓词由指定的类实现。 为了归结一个类的谓词: 该类必须实现待归结的谓词,意指该谓词必须源于本应继承的同一谓词。 该类必须在继承段中提到。,2004.11.3,AI程序设计,29,13.3.3 归结限定,谓词重命名归结 谓词重命名归结(

28、Predicate Rename Resolution)声明一个谓词以另外一个名字被实现。该谓词必须来自一个继承类,并且它的类型、模式和流必须确实匹配。 predicateRenameResolution : predicateNameWithArity from className : predicateName 接口归结 接口归结(Interface Resolution)用于归结来自继承类的完整接口。这样,一个接口归结就成为声明接口中所有的谓词应当由同一类归结的一个捷径。 interfaceResolution : interface interfaceName from classNa

29、me,2004.11.3,AI程序设计,30,13.3.3 归结限定,外部归结 一个谓词的外部归结(External Resolution)声明该谓词并没有在类本身中被实现,而是在外部程序库中被实现的。外部归结只能用于类谓词,即对象谓词不能被外部归结。 在程序库中,调用约定、连接名和参数类型要与实现相符是非常重要的。 私有的和公有的谓词都能被外部归结。 predicateExternallyResolution : predicateNameWithArity externally,2004.11.3,AI程序设计,31,13.3.3 归结限定,动态外部归结 一个谓词的外部归结也向来自DLL的

30、私有和公共类谓词的动态载入提供语法。该语法是: predicateExternallyResolutionFromDLL : predicateNameWithArity externally from DllNameWithPath DllNameWithPath : stringLiteral 如果谓词predicateNameWithArity在DLL DllNameWithPath中被丢失,那么动态载入就给运行程序提供了可能性,直到实际调用这个被丢失的谓词为止。在这样的调用中将出现运行时错误。,2004.11.3,AI程序设计,32,13.3.4 委托限定,一个委托段包括许多的委托:

31、delegateQualification : delegate delegation-comma-sep-list delegation : predicateDelegation interfaceDelegation 委托限定用于将对象谓词的执行委托给指定的源。 有两种委托限定,即谓词委托和接口委托。接口委托,用于将一个接口声明的一整套对象谓词的实现委托给另一个作为事实变量存储的对象的实现。这样,一个接口委托就成为声明以下内容的一个捷径,即接口中所有谓词的实现应当委托给以事实变量存储的对象的实现。 委托段除了它是委托给那些保持类的构造对象的事实变量而不是委托给继承类之外,它看起来像是归结

32、段的对应物(谓词或接口)。,2004.11.3,AI程序设计,33,13.3.4 委托限定,谓词委托 对象谓词委托(Predicate Delegation)声明该谓词的功能被委托给以事实变量factVariable_of_InterfaceType所指定的对象中的谓词。 predicateDelegation : predicateNameWithArity to factVariable_of_InterfaceType,2004.11.3,AI程序设计,34,13.3.4 委托限定,考察下面的例子: interface a predicates p1 : () procedure ()

33、. p2 : () procedure () . end interface interface aa supports a end interface class bb_class : a end class class cc_class : a end class,class dd_class : aa constructors new : (a First, a Second). end class implement dd_class delegate p1/0 to fv1, p2/0 to fv2 facts fv1 : a . fv2 : a . clauses new(I,J)

34、:- fv1 := I, fv2 := J. end implement,2004.11.3,AI程序设计,35,13.3.4 委托限定,随后可以构造类型a的对象并把它们赋给以事实变量fv1和 fv2来定义对象,从而定义真正委托p1和p2功能性定义的类的对象。考虑下列例子: goal O_bb = bb_class:new(), O_cc = cc_class:new(), O_dd = dd_class:new(O_bb, O_cc), O_dd : p1(), % This p1 from O_bb object O_dd : p2(). % This p2 from O_cc objec

35、t,2004.11.3,AI程序设计,36,13.3.4 委托限定,实际上,Visual Prolog的委托具有与向dd_class的实现添加子句一样的效果,dd_class由谓词的功能是“输出”的类的对象明确指定。例如,好像在dd_class的实现中确定了下面的子句: clauses p1() :- fv1 : p1().,2004.11.3,AI程序设计,37,13.3.4 委托限定,接口委托 当需要指定在接口interfaceName中声明的所有谓词的功能被委托到来自同一被继承类的对象的谓词时,可以使用接口委托说明: interfaceDelegation : interface int

36、erfaceName to factVariable_of_InterfaceType 这样接口委托就是一个捷径,声明了接口interfaceName中声明的所有谓词的功能应当被委托给以事实变量factVariable_of_InterfaceType存储的对象。对象被赋以事实变量factVariable_of_InterfaceType,该变量是interfaceName 类型(或其子类型)的。,2004.11.3,AI程序设计,38,13.3.4 委托限定,委托一个接口给一个通过事实变量传递的对象: 事实变量 factVariable_of_InterfaceType 必须具有一个接口in

37、terfaceName 的类型或其子类型。 对象所支持的接口必须被构造出来并被赋值给事实变量factVariable_of_InterfaceType。 谓词委托比接口委托优先级更高。如果一个谓词的两种委托都被指定,就是说谓词委托被指定到谓词,并且在具有接口委托的接口中被声明。那么具有较高优先权的谓词委托将被执行。,2004.11.3,AI程序设计,39,13.3.5 This修饰,对象谓词总是在一个对象中被调用。这个对象携带该对象的事实,并且包含在对象谓词的实现中。对象谓词有权使用隐含的对象。这样的对象被称为“This“。有两种“This“的访问,即隐式访问和显式访问。 1) 显式“This

38、“ 在每个对象谓词的每个子句中,变量This被隐含地定义并绑定到“This”,也就是其成员谓词正在执行的对象。 2) 隐式“This“ 在一个对象成员谓词的子句中,可以直接调用另一对象成员谓词,因为“This”是被隐含地包含的运算。只要调用的方法含义明确,超类的成员也可以被直接调用(参见作用域和可视性)。同样地,对象事实(存储在“This”中)也可以被访问。,2004.11.3,AI程序设计,40,13.3.5 This修饰,3)This和继承 “This“总是引用一个属于用“This“的类的对象,假定接口aa被声明如下: interface aa predicates action : ()

39、 procedure (). doAction : () procedure (). end interface 再假定类aa_class如下: class aa_class : aa end class 然后执行: implement aa_class clauses action() :- doAction(), This:doAction(). doAction() :- write(“aa_class:doAction“), nl. end implement,2004.11.3,AI程序设计,41,下面的目标: goal A = aa_class:new(), A:action().

40、 将输出: aa_class:doAction aa_class:doAction,现在再考虑类bb_class,其声明如下: class bb_class : aa end class 其实现如下: implement bb_class inherits aa_class clauses doAction() :- write(“bb_class:doAction“), nl. end implement 下列目标: goal B = bb_class:new(), B:action(). 也将输出: aa_class:doAction aa_class:doAction,这是因为在隐式和显

41、式情况下,aa_class中的“This“都引用了类aa_class的对象。,2004.11.3,AI程序设计,42,13.3.6 构造器,本节介绍对象的构造,同样地,它只涉及产生对象的类。通过调用构造器构 造对象。构造器在类声明和类实现的构造器段中明确地声明。(参见缺省构造 器) 一个构造器实际上有两个相关的谓词: 一个类函数,返回新构造好的对象。 一个对象谓词,当初始化继承对象时使用。 这个相关的对象谓词用于执行该对象的初始化。这个谓词只能从类自身的构 造器中,以及从该类的继承类的构造器中被调用(即基本类初始化)。 这个相关的类函数是隐含定义的,即任何地方都不存在它的子句。,2004.11

42、.3,AI程序设计,43,13.3.6.1 缺省构造器,缺省构造器是一个名为new的空变元构造器。如果一个类根本就没有声明任何构造器,那么它就隐含地声明了缺省构造器。就是说所有子句至少具有一个构造器。显式地重新定义缺省构造器也是合法的。 不需要定义(即实现)缺省构造器;如果它没有定义,则一个无效的定义隐含地被假定。,2004.11.3,AI程序设计,44,13.3.6.1 缺省构造器,举例 假定一个接口aa,考查下面代码: class aa_class : aa end class 类aa_class没有声明构造器;因此,它隐含地声明了缺省构造器。这样可以创建一个如下的类aa_class对象:

43、 goal _A = aa_class:new(). % implicitly declared default constructor,2004.11.3,AI程序设计,45,13.3.6.1 缺省构造器,举例 实现类aa_class隐含声明的缺省构造器是合法的: implement aa_class clauses new() :- . end implement,2004.11.3,AI程序设计,46,13.3.6.2 子对象构造,所有的构造器都负责将被构造的对象初始化为有效状态。为了获得这样的有效状态,所有的子对象(即继承类)也必须被初始化。 子对象可以通过两种方式中的任意一种来初始化

44、。这两种方式或者是程序调用一个继承类的构造器,或者是自动调用缺省的构造器。后者实际上要求继承类具有缺省的构造器。 如果继承类不具有缺省构造器,那么必须显式地调用其它的构造器。在具有子句的事实和事实变量的初始化之后,在进入构造器的子句之前,必须立即执行继承类的构造器的缺省调用。 通过没有返回值的形式调用继承类的构造器。如果你的调用是有返回值的形式,实际上是创建了一个新的对象而不是调用“This”中的构造器。(参见下面的例子),2004.11.3,AI程序设计,47,13.3.6.2 子对象构造,举例 类bb_class的实现继承了类aa_class,并且bb_class的缺省构造器用一个最新创建

45、的cc_class对象来调用aa_class的构造器。 implement bb_class inherits aa_class clauses new() :- C = cc_class:new(), % create a cc_class object aa_class:newC(C). % invoke constructor on inherited sub-object . end implement,2004.11.3,AI程序设计,48,13.3.6.3 单个(对象)事实初始化,正如所有的构造器必须初始化或构造子对象一样,它们也必须在首次引用对象的单个事实之前,对所有这些事实进行

46、初始化。 注意,单个类事实只能用子句初始化,因为它们与对象无关。一个类事实可以在创建第一个对象之前被访问。,2004.11.3,AI程序设计,49,13.3.6.3 单个(对象)事实初始化,举例 implement bb_class inherits aa_class facts counter : integer := 0. point : (integer X, integer Y) single. c : (cc C) single. clauses point(0, 1). % The object is created and counter and point are initia

47、lized before entrance, % the default constructor aa_class:new/0 is also invoked before entrance new() :- C = cc_class:new(), assert(c(C). . end implement,这个例子表明: (1)怎样通过一个表达式初始化一个事实变量; (2)怎样通过一个子句初始化一个单个事实(点); (3)怎样在构造器中初始化一个单个事实; (4)在哪里调用一个继承类的缺省构造器。,2004.11.3,AI程序设计,50,13.3.6.4 委托构造,作为用构造器直接构造对象的选

48、择方案,可以将这一任务委托给同一个类的另一构造器。这一点仅仅通过调用另外一个构造器就可以实现(即不返回值的形式)。委托构造的时候必须确保已经实际构造了对象,并且不是“重复构造 (over-constructed)”。单个事实可以被赋值任意多次,因此它不能“重复构造”。另一方面,继承类在对象构造期间只能被初始化一次。,2004.11.3,AI程序设计,51,13.3.6.4 委托构造,举例 这个例子说明了一个以委托方式构造的典型应用。一个构造器(new/0)用缺省值调用另外一个构造器(newFromC/1)。 implement aa_class facts c : (cc C) single.

49、 clauses new() :- C = cc_class:new(), newFromC(C). newFromC(C) :- assert(c(C). . end implement,2004.11.3,AI程序设计,52,13.3.6.5 构造对象的规则,程序员必须确保: 所有子对象都只能被初始化或构造一次。 所有单个事实都应被初始化至少一次。 在子对象被初始化或构造之前,没有子对象被引用。 在单个事实被初始化之前没有被使用。 在编译时间内编译器能否检测出上述问题并不能得到保证。 编译器可以提示产生一个运行时间确认,它也可以提示非安全地省略这些运行时间确认。,2004.11.3,AI程序设计,53,13.3.7 终结,一旦程序不能到达一个对象,这个对象就被终结。语义上并不能确切地指出这个对象何时会终结。惟一能够确定的是,只要程序还能到达对象就不会终结。习惯上,当对象被垃圾回收程序废弃的时候,它就终结了。终结是构造的对立面,并将对象从内存中删除。 类也可以实现一个终结器,它是一个对象终结时(从内存被删除之前)调用的谓词。 一个终结器是一个名为finalize,没有参数也没有返回值的过程。这个谓词隐含地被声明,并且不能由程序直接调用。 终结器的主要用途是释放外部资源,但是

展开阅读全文
相关资源
猜你喜欢
相关搜索

当前位置:首页 > 其他


经营许可证编号:宁ICP备18001539号-1