<?xml version="1.0"?>
<feed xmlns="http://www.w3.org/2005/Atom" xml:lang="en">
	<id>https://wiki.visual-prolog.com/index.php?action=history&amp;feed=atom&amp;title=Introduction_to_Classes_and_Objects%EF%BC%88%E7%B1%BB%E4%B8%8E%E5%AF%B9%E8%B1%A1%EF%BC%89</id>
	<title>Introduction to Classes and Objects（类与对象） - Revision history</title>
	<link rel="self" type="application/atom+xml" href="https://wiki.visual-prolog.com/index.php?action=history&amp;feed=atom&amp;title=Introduction_to_Classes_and_Objects%EF%BC%88%E7%B1%BB%E4%B8%8E%E5%AF%B9%E8%B1%A1%EF%BC%89"/>
	<link rel="alternate" type="text/html" href="https://wiki.visual-prolog.com/index.php?title=Introduction_to_Classes_and_Objects%EF%BC%88%E7%B1%BB%E4%B8%8E%E5%AF%B9%E8%B1%A1%EF%BC%89&amp;action=history"/>
	<updated>2026-04-13T08:03:54Z</updated>
	<subtitle>Revision history for this page on the wiki</subtitle>
	<generator>MediaWiki 1.37.1</generator>
	<entry>
		<id>https://wiki.visual-prolog.com/index.php?title=Introduction_to_Classes_and_Objects%EF%BC%88%E7%B1%BB%E4%B8%8E%E5%AF%B9%E8%B1%A1%EF%BC%89&amp;diff=4347&amp;oldid=prev</id>
		<title>Yiding: /* 继承 */</title>
		<link rel="alternate" type="text/html" href="https://wiki.visual-prolog.com/index.php?title=Introduction_to_Classes_and_Objects%EF%BC%88%E7%B1%BB%E4%B8%8E%E5%AF%B9%E8%B1%A1%EF%BC%89&amp;diff=4347&amp;oldid=prev"/>
		<updated>2017-02-28T01:48:47Z</updated>

		<summary type="html">&lt;p&gt;&lt;span dir=&quot;auto&quot;&gt;&lt;span class=&quot;autocomment&quot;&gt;继承&lt;/span&gt;&lt;/span&gt;&lt;/p&gt;
&lt;table style=&quot;background-color: #fff; color: #202122;&quot; data-mw=&quot;interface&quot;&gt;
				&lt;col class=&quot;diff-marker&quot; /&gt;
				&lt;col class=&quot;diff-content&quot; /&gt;
				&lt;col class=&quot;diff-marker&quot; /&gt;
				&lt;col class=&quot;diff-content&quot; /&gt;
				&lt;tr class=&quot;diff-title&quot; lang=&quot;en&quot;&gt;
				&lt;td colspan=&quot;2&quot; style=&quot;background-color: #fff; color: #202122; text-align: center;&quot;&gt;← Older revision&lt;/td&gt;
				&lt;td colspan=&quot;2&quot; style=&quot;background-color: #fff; color: #202122; text-align: center;&quot;&gt;Revision as of 03:48, 28 February 2017&lt;/td&gt;
				&lt;/tr&gt;&lt;tr&gt;&lt;td colspan=&quot;2&quot; class=&quot;diff-lineno&quot; id=&quot;mw-diff-left-l216&quot;&gt;Line 216:&lt;/td&gt;
&lt;td colspan=&quot;2&quot; class=&quot;diff-lineno&quot;&gt;Line 216:&lt;/td&gt;&lt;/tr&gt;
&lt;tr&gt;&lt;td class=&quot;diff-marker&quot;&gt;&lt;/td&gt;&lt;td style=&quot;background-color: #f8f9fa; color: #202122; font-size: 88%; border-style: solid; border-width: 1px 1px 1px 4px; border-radius: 0.33em; border-color: #eaecf0; vertical-align: top; white-space: pre-wrap;&quot;&gt;&lt;div&gt;==继承==&lt;/div&gt;&lt;/td&gt;&lt;td class=&quot;diff-marker&quot;&gt;&lt;/td&gt;&lt;td style=&quot;background-color: #f8f9fa; color: #202122; font-size: 88%; border-style: solid; border-width: 1px 1px 1px 4px; border-radius: 0.33em; border-color: #eaecf0; vertical-align: top; white-space: pre-wrap;&quot;&gt;&lt;div&gt;==继承==&lt;/div&gt;&lt;/td&gt;&lt;/tr&gt;
&lt;tr&gt;&lt;td class=&quot;diff-marker&quot;&gt;&lt;/td&gt;&lt;td style=&quot;background-color: #f8f9fa; color: #202122; font-size: 88%; border-style: solid; border-width: 1px 1px 1px 4px; border-radius: 0.33em; border-color: #eaecf0; vertical-align: top; white-space: pre-wrap;&quot;&gt;&lt;br/&gt;&lt;/td&gt;&lt;td class=&quot;diff-marker&quot;&gt;&lt;/td&gt;&lt;td style=&quot;background-color: #f8f9fa; color: #202122; font-size: 88%; border-style: solid; border-width: 1px 1px 1px 4px; border-radius: 0.33em; border-color: #eaecf0; vertical-align: top; white-space: pre-wrap;&quot;&gt;&lt;br/&gt;&lt;/td&gt;&lt;/tr&gt;
&lt;tr&gt;&lt;td class=&quot;diff-marker&quot; data-marker=&quot;−&quot;&gt;&lt;/td&gt;&lt;td style=&quot;color: #202122; font-size: 88%; border-style: solid; border-width: 1px 1px 1px 4px; border-radius: 0.33em; border-color: #ffe49c; vertical-align: top; white-space: pre-wrap;&quot;&gt;&lt;div&gt;&lt;del style=&quot;font-weight: bold; text-decoration: none;&quot;&gt;当实现user类时，当然想要利用已有的两个person类。假设我们想要user类与person类差不多，只不过是还需要处理口令。这样，我们可以让user类从person类中 &lt;/del&gt;inherit （继承）person那部分的实现。下面的代码就可以做到这个要求：  &lt;/div&gt;&lt;/td&gt;&lt;td class=&quot;diff-marker&quot; data-marker=&quot;+&quot;&gt;&lt;/td&gt;&lt;td style=&quot;color: #202122; font-size: 88%; border-style: solid; border-width: 1px 1px 1px 4px; border-radius: 0.33em; border-color: #a3d3ff; vertical-align: top; white-space: pre-wrap;&quot;&gt;&lt;div&gt;&lt;ins style=&quot;font-weight: bold; text-decoration: none;&quot;&gt;当实现user类时，当然想要利用已有的那个person类。假设我们想要user类与person类差不多，只不过是还需要处理口令。这样，我们可以让user类从person类中 &lt;/ins&gt;inherit （继承）person那部分的实现。下面的代码就可以做到这个要求：  &lt;/div&gt;&lt;/td&gt;&lt;/tr&gt;
&lt;tr&gt;&lt;td class=&quot;diff-marker&quot;&gt;&lt;/td&gt;&lt;td style=&quot;background-color: #f8f9fa; color: #202122; font-size: 88%; border-style: solid; border-width: 1px 1px 1px 4px; border-radius: 0.33em; border-color: #eaecf0; vertical-align: top; white-space: pre-wrap;&quot;&gt;&lt;br/&gt;&lt;/td&gt;&lt;td class=&quot;diff-marker&quot;&gt;&lt;/td&gt;&lt;td style=&quot;background-color: #f8f9fa; color: #202122; font-size: 88%; border-style: solid; border-width: 1px 1px 1px 4px; border-radius: 0.33em; border-color: #eaecf0; vertical-align: top; white-space: pre-wrap;&quot;&gt;&lt;br/&gt;&lt;/td&gt;&lt;/tr&gt;
&lt;tr&gt;&lt;td class=&quot;diff-marker&quot;&gt;&lt;/td&gt;&lt;td style=&quot;background-color: #f8f9fa; color: #202122; font-size: 88%; border-style: solid; border-width: 1px 1px 1px 4px; border-radius: 0.33em; border-color: #eaecf0; vertical-align: top; white-space: pre-wrap;&quot;&gt;&lt;div&gt;&amp;lt;vip&amp;gt;implement user&lt;/div&gt;&lt;/td&gt;&lt;td class=&quot;diff-marker&quot;&gt;&lt;/td&gt;&lt;td style=&quot;background-color: #f8f9fa; color: #202122; font-size: 88%; border-style: solid; border-width: 1px 1px 1px 4px; border-radius: 0.33em; border-color: #eaecf0; vertical-align: top; white-space: pre-wrap;&quot;&gt;&lt;div&gt;&amp;lt;vip&amp;gt;implement user&lt;/div&gt;&lt;/td&gt;&lt;/tr&gt;
&lt;/table&gt;</summary>
		<author><name>Yiding</name></author>
	</entry>
	<entry>
		<id>https://wiki.visual-prolog.com/index.php?title=Introduction_to_Classes_and_Objects%EF%BC%88%E7%B1%BB%E4%B8%8E%E5%AF%B9%E8%B1%A1%EF%BC%89&amp;diff=4112&amp;oldid=prev</id>
		<title>Yiding: /* 参考 */</title>
		<link rel="alternate" type="text/html" href="https://wiki.visual-prolog.com/index.php?title=Introduction_to_Classes_and_Objects%EF%BC%88%E7%B1%BB%E4%B8%8E%E5%AF%B9%E8%B1%A1%EF%BC%89&amp;diff=4112&amp;oldid=prev"/>
		<updated>2015-06-17T12:12:03Z</updated>

		<summary type="html">&lt;p&gt;&lt;span dir=&quot;auto&quot;&gt;&lt;span class=&quot;autocomment&quot;&gt;参考&lt;/span&gt;&lt;/span&gt;&lt;/p&gt;
&lt;table style=&quot;background-color: #fff; color: #202122;&quot; data-mw=&quot;interface&quot;&gt;
				&lt;col class=&quot;diff-marker&quot; /&gt;
				&lt;col class=&quot;diff-content&quot; /&gt;
				&lt;col class=&quot;diff-marker&quot; /&gt;
				&lt;col class=&quot;diff-content&quot; /&gt;
				&lt;tr class=&quot;diff-title&quot; lang=&quot;en&quot;&gt;
				&lt;td colspan=&quot;2&quot; style=&quot;background-color: #fff; color: #202122; text-align: center;&quot;&gt;← Older revision&lt;/td&gt;
				&lt;td colspan=&quot;2&quot; style=&quot;background-color: #fff; color: #202122; text-align: center;&quot;&gt;Revision as of 14:12, 17 June 2015&lt;/td&gt;
				&lt;/tr&gt;&lt;tr&gt;&lt;td colspan=&quot;2&quot; class=&quot;diff-lineno&quot; id=&quot;mw-diff-left-l286&quot;&gt;Line 286:&lt;/td&gt;
&lt;td colspan=&quot;2&quot; class=&quot;diff-lineno&quot;&gt;Line 286:&lt;/td&gt;&lt;/tr&gt;
&lt;tr&gt;&lt;td class=&quot;diff-marker&quot;&gt;&lt;/td&gt;&lt;td style=&quot;background-color: #f8f9fa; color: #202122; font-size: 88%; border-style: solid; border-width: 1px 1px 1px 4px; border-radius: 0.33em; border-color: #eaecf0; vertical-align: top; white-space: pre-wrap;&quot;&gt;&lt;div&gt;==参考==&lt;/div&gt;&lt;/td&gt;&lt;td class=&quot;diff-marker&quot;&gt;&lt;/td&gt;&lt;td style=&quot;background-color: #f8f9fa; color: #202122; font-size: 88%; border-style: solid; border-width: 1px 1px 1px 4px; border-radius: 0.33em; border-color: #eaecf0; vertical-align: top; white-space: pre-wrap;&quot;&gt;&lt;div&gt;==参考==&lt;/div&gt;&lt;/td&gt;&lt;/tr&gt;
&lt;tr&gt;&lt;td class=&quot;diff-marker&quot;&gt;&lt;/td&gt;&lt;td style=&quot;background-color: #f8f9fa; color: #202122; font-size: 88%; border-style: solid; border-width: 1px 1px 1px 4px; border-radius: 0.33em; border-color: #eaecf0; vertical-align: top; white-space: pre-wrap;&quot;&gt;&lt;br/&gt;&lt;/td&gt;&lt;td class=&quot;diff-marker&quot;&gt;&lt;/td&gt;&lt;td style=&quot;background-color: #f8f9fa; color: #202122; font-size: 88%; border-style: solid; border-width: 1px 1px 1px 4px; border-radius: 0.33em; border-color: #eaecf0; vertical-align: top; white-space: pre-wrap;&quot;&gt;&lt;br/&gt;&lt;/td&gt;&lt;/tr&gt;
&lt;tr&gt;&lt;td class=&quot;diff-marker&quot; data-marker=&quot;−&quot;&gt;&lt;/td&gt;&lt;td style=&quot;color: #202122; font-size: 88%; border-style: solid; border-width: 1px 1px 1px 4px; border-radius: 0.33em; border-color: #ffe49c; vertical-align: top; white-space: pre-wrap;&quot;&gt;&lt;div&gt;[[Category:&lt;del style=&quot;font-weight: bold; text-decoration: none;&quot;&gt;Tutorials&lt;/del&gt;]]&lt;/div&gt;&lt;/td&gt;&lt;td class=&quot;diff-marker&quot; data-marker=&quot;+&quot;&gt;&lt;/td&gt;&lt;td style=&quot;color: #202122; font-size: 88%; border-style: solid; border-width: 1px 1px 1px 4px; border-radius: 0.33em; border-color: #a3d3ff; vertical-align: top; white-space: pre-wrap;&quot;&gt;&lt;div&gt;[[Category:&lt;ins style=&quot;font-weight: bold; text-decoration: none;&quot;&gt;Tutorials部分中文译文&lt;/ins&gt;]]&lt;/div&gt;&lt;/td&gt;&lt;/tr&gt;
&lt;/table&gt;</summary>
		<author><name>Yiding</name></author>
	</entry>
	<entry>
		<id>https://wiki.visual-prolog.com/index.php?title=Introduction_to_Classes_and_Objects%EF%BC%88%E7%B1%BB%E4%B8%8E%E5%AF%B9%E8%B1%A1%EF%BC%89&amp;diff=4110&amp;oldid=prev</id>
		<title>Yiding: Created page with &quot;（以下内容译自:Category:Tutorials中的Introduction to Classes and Objects。）  本文的目的是概要介绍Visual Prolog中的面向对象的概念，并对相关...&quot;</title>
		<link rel="alternate" type="text/html" href="https://wiki.visual-prolog.com/index.php?title=Introduction_to_Classes_and_Objects%EF%BC%88%E7%B1%BB%E4%B8%8E%E5%AF%B9%E8%B1%A1%EF%BC%89&amp;diff=4110&amp;oldid=prev"/>
		<updated>2015-06-17T12:05:49Z</updated>

		<summary type="html">&lt;p&gt;Created page with &amp;quot;（以下内容译自&lt;a href=&quot;/index.php?title=Category:Tutorials&quot; title=&quot;Category:Tutorials&quot;&gt;Category:Tutorials&lt;/a&gt;中的Introduction to Classes and Objects。）  本文的目的是概要介绍Visual Prolog中的面向对象的概念，并对相关...&amp;quot;&lt;/p&gt;
&lt;p&gt;&lt;b&gt;New page&lt;/b&gt;&lt;/p&gt;&lt;div&gt;（以下内容译自[[:Category:Tutorials]]中的Introduction to Classes and Objects。）&lt;br /&gt;
&lt;br /&gt;
本文的目的是概要介绍Visual Prolog中的面向对象的概念，并对相关语法做些举例说明。 &lt;br /&gt;
&lt;br /&gt;
==对象模型==&lt;br /&gt;
在Visual Prolog的 object model（对象模型） 中，主要的语义实体是 objects（对象）、对象类型及类。而涉及这些实体的主要语法概念则是接口、类的声明和实现。 &lt;br /&gt;
&lt;br /&gt;
interface（接口） 是一组命名了的谓词声明，它描述了对象的“界面”（因而称之为interface），也就是从对象外部访问对象的通道。接口就代表了对象类型（object types）。 &lt;br /&gt;
&lt;br /&gt;
来看下面这个接口定义：&lt;br /&gt;
&lt;br /&gt;
&amp;lt;vip&amp;gt;interface person&lt;br /&gt;
predicates&lt;br /&gt;
    getName : () -&amp;gt; string Name.&lt;br /&gt;
    setName : (string Name).&lt;br /&gt;
end interface person&amp;lt;/vip&amp;gt;&lt;br /&gt;
这是一个叫做person的接口的定义。所有person类型的对象都有两个谓词：getName 和 setName，如同上面声明的那样。&lt;br /&gt;
&lt;br /&gt;
接口只是定义对象的类型，而类才创建对象。类有declaration（声明）和implementation（实现）。构造（constructs）person对象的类，可以像这样：&lt;br /&gt;
&lt;br /&gt;
&amp;lt;vip&amp;gt;class person : person&lt;br /&gt;
constructors&lt;br /&gt;
    new : (string Name).&lt;br /&gt;
end class person&amp;lt;/vip&amp;gt;&lt;br /&gt;
&lt;br /&gt;
这是名为person的类的声明，这个类构造person类型的对象。 该类有个名为new的构造器（constructor），只要给它一个 Name，它就会构造一个（person类型的）对象。&lt;br /&gt;
&lt;br /&gt;
类还需要有实现，可以是这样的：&lt;br /&gt;
&lt;br /&gt;
&amp;lt;vip&amp;gt;implement person&lt;br /&gt;
facts&lt;br /&gt;
    name : string.&lt;br /&gt;
 &lt;br /&gt;
clauses&lt;br /&gt;
    new(Name) :- name := Name.&lt;br /&gt;
 &lt;br /&gt;
clauses&lt;br /&gt;
    getName() = name.&lt;br /&gt;
 &lt;br /&gt;
clauses&lt;br /&gt;
    setName(Name) :- name := Name.&lt;br /&gt;
end implement person&amp;lt;/vip&amp;gt;&lt;br /&gt;
&lt;br /&gt;
它是person类的实现。实现必须为各公共谓词及构造器提供定义，在这里就是 new、getName 和 setName。实现也可以局部地声明和定义额外的实体，这些实体只能在实现内部访问。这个例子中，类声明了一个名为name的事实变量，它用于保存人的姓名。 &lt;br /&gt;
&lt;br /&gt;
每个对象有自己的事实变量name的实例，而上面子句的代码会引述特定的事实变量实例。我们称这样的谓词是对象谓词（object predicates）而那个事实是对象事实（object fact）。 &lt;br /&gt;
&lt;br /&gt;
==类实体==&lt;br /&gt;
&lt;br /&gt;
类还可以有类中所有对象共享的实体。 我们仍用上面的例子，再扩充一下，加上一些代码对创建了多少个person对象来计数。每创建一个对象，计数就加一。&lt;br /&gt;
&lt;br /&gt;
先扩充一下类的声明，增加一个谓词 getCreatedCount，它会返回当前的计数值。 &lt;br /&gt;
&lt;br /&gt;
&amp;lt;vip&amp;gt;class person : person&lt;br /&gt;
constructors&lt;br /&gt;
    new : (string Name).&lt;br /&gt;
 &lt;br /&gt;
predicates&lt;br /&gt;
    getCreatedCount : () -&amp;gt; unsigned Count.&lt;br /&gt;
end class person&amp;lt;/vip&amp;gt;&lt;br /&gt;
&lt;br /&gt;
注意，公用的类谓词（class predicates）是在类声明中声明的，而公用的对象谓词（object predicates）则是在接口中声明的。这是一个没有特例的规则：不可能在类声明中声明对象谓词，也不可能在接口中声明类谓词。&lt;br /&gt;
&lt;br /&gt;
增加的谓词还需要有类实现中的定义，这里还需要一个事实来保存计数值，这个事实必须是类事实（class fact，它是由所有对象共享的）。在类的实现（implementation）中可以声明和定义私有的对象实体及私有的类实体。要声明类实体，需要把相应的声明段加上class关键字。总之，类person的实现可以是这样：&lt;br /&gt;
&lt;br /&gt;
&amp;lt;vip&amp;gt;implement person&lt;br /&gt;
class facts&lt;br /&gt;
    createdCount : unsigned := 0.&lt;br /&gt;
 &lt;br /&gt;
clauses&lt;br /&gt;
    getCreatedCount() = createdCount.&lt;br /&gt;
 &lt;br /&gt;
facts&lt;br /&gt;
    name : string.&lt;br /&gt;
 &lt;br /&gt;
clauses&lt;br /&gt;
    new(Name) :-&lt;br /&gt;
        name := Name,&lt;br /&gt;
        createdCount := createdCount+1.&lt;br /&gt;
 &lt;br /&gt;
clauses&lt;br /&gt;
    getName() = name.&lt;br /&gt;
 &lt;br /&gt;
clauses&lt;br /&gt;
    setName(Name) :- name := Name.&lt;br /&gt;
end implement person&amp;lt;/vip&amp;gt;&lt;br /&gt;
&lt;br /&gt;
上面，增加了一个被初始化为零的类事实createdCount；增加了一个返回createdCount当前值的谓词getCreatedCount；还在构造器中增加对createdCount加一的代码。&lt;br /&gt;
&lt;br /&gt;
注意一下构造器，两个赋值形式上是一样的，但一个更新的是对象的状态而另一个则改变的是类的状态。 &lt;br /&gt;
&lt;br /&gt;
==模块==&lt;br /&gt;
&lt;br /&gt;
类有一个特殊的变种，它根本不产生对象，这样的类更像是一个模块。不构造对象的类（或简单说模块），声明时就不需要对象类型了：&lt;br /&gt;
&lt;br /&gt;
&amp;lt;vip&amp;gt;class io % 这里没有类型&lt;br /&gt;
predicates&lt;br /&gt;
    write : (string ToWrite).&lt;br /&gt;
    write : (unsigned ToWrite).&lt;br /&gt;
end class io&amp;lt;/vip&amp;gt;&lt;br /&gt;
&lt;br /&gt;
这样不产生对象的类显然不能有对象实体，也不能有构造器。 &lt;br /&gt;
&lt;br /&gt;
==创建与访问==&lt;br /&gt;
&lt;br /&gt;
利用上面的代码，再建立一个可创建对象并用io类（这里不用管它是如何实现的）写出person姓名的目标（goal）。 &lt;br /&gt;
&lt;br /&gt;
&amp;lt;vip&amp;gt;goal&lt;br /&gt;
    P = person::new(&amp;quot;John&amp;quot;),&lt;br /&gt;
    Name = P:getName(),&lt;br /&gt;
    io::write(Name).&amp;lt;/vip&amp;gt;&lt;br /&gt;
&lt;br /&gt;
上面的第一行，调用person类中的构造器 new ，创建的对象约束给变量P。再下一行，将在P上调用对象谓词 getName 的结果约束变量 Name。最后一行，调用io类中的类谓词来写。&lt;br /&gt;
&lt;br /&gt;
注意一下，类中的名称引用时用双冒号，如 person::new；而引用对象谓词时用单个冒号，如 P:getName 。 &lt;br /&gt;
&lt;br /&gt;
还需要注意，尽管构造器的声明不像是个函数，但它是一个返回对象的函数，而返回类型则包含在类声明中。&lt;br /&gt;
&lt;br /&gt;
==接口是对象的类型==&lt;br /&gt;
&lt;br /&gt;
上面说过，接口就是对象的类型。 This should be taken literally, you can use interfaces in the same places where you can use non-object types. 例如，在下面的谓词声明中： &lt;br /&gt;
&lt;br /&gt;
&amp;lt;vip&amp;gt;class mail&lt;br /&gt;
predicates&lt;br /&gt;
    sendMessage : (person Recipient, string Message).&lt;br /&gt;
end class mail&amp;lt;/vip&amp;gt;&lt;br /&gt;
&lt;br /&gt;
谓词 mail::sendMessage 以 person 和 string 作为参数。&lt;br /&gt;
&lt;br /&gt;
==多重实现==&lt;br /&gt;
&lt;br /&gt;
可以建立若干完全不同的类，这些类都可以创建person对象，这只需要声明和实现多个类来构造person对象。类的实现可以大不同，如，创建一个类把person保存在一个数据库中。它可以这样声明： &lt;br /&gt;
&lt;br /&gt;
&amp;lt;vip&amp;gt;class personInDB : person&lt;br /&gt;
constructors&lt;br /&gt;
    new : (string DatabaseName, string Name).&lt;br /&gt;
end class personInDB&amp;lt;/vip&amp;gt;&lt;br /&gt;
&lt;br /&gt;
在这里，我们不去关心这样或那样的实际实现，不过我们还是给出下面的代码，显示对某个对象类型，可以有完全不同的实现。&lt;br /&gt;
&lt;br /&gt;
&amp;lt;vip&amp;gt;implement personInDB&lt;br /&gt;
facts&lt;br /&gt;
    db : myDatabase.&lt;br /&gt;
    personID : unsigned.&lt;br /&gt;
 &lt;br /&gt;
clauses&lt;br /&gt;
    new(DatabaseName, Name) :-&lt;br /&gt;
        db := myDatabase::getDB(DatabaseName),&lt;br /&gt;
        personID := db:storePerson(Name).&lt;br /&gt;
 &lt;br /&gt;
clauses&lt;br /&gt;
    getName() = db:getPersonName(personID).&lt;br /&gt;
 &lt;br /&gt;
clauses&lt;br /&gt;
    setName(Name) :- db:setPersonName(personID, Name).&lt;br /&gt;
end implement personInDB&amp;lt;/vip&amp;gt;&lt;br /&gt;
&lt;br /&gt;
可以看到，不光是内部的行为完全不同了，而且内部的状态也有了完全不同的结构与内容。&lt;br /&gt;
&lt;br /&gt;
==包容多态==&lt;br /&gt;
&lt;br /&gt;
相同类型的对象可以用在相同的关联中，而不用去管各自的实现有多大差别。例如，可以用上面的mail类给某个person发送消息，不管这个person是由person类构造的还是personInDB类构造的都行： &lt;br /&gt;
&lt;br /&gt;
&amp;lt;vip&amp;gt;goal&lt;br /&gt;
    P1 = person::new(&amp;quot;John&amp;quot;),&lt;br /&gt;
    mail::sendMessage(P1, &amp;quot;Hi John, ...&amp;quot;),&lt;br /&gt;
    P2 = personInDB::new(&amp;quot;Paul&amp;quot;),&lt;br /&gt;
    mail::sendMessage(P2, &amp;quot;Hi Paul, ...&amp;quot;).&amp;lt;/vip&amp;gt;&lt;br /&gt;
&lt;br /&gt;
这个特性就是所谓包容：一个类构造的对象与另一个类构造的对象都可以适应特定关联，只要这两个对象都具有关联所要求的类型。&lt;br /&gt;
&lt;br /&gt;
可以看到，谓词 mail::sendMessage 可以用任一个person类的对象，因而从某种意义上说它是多态的（包容多态）。 &lt;br /&gt;
&lt;br /&gt;
==支持 （类型的扩展）==&lt;br /&gt;
&lt;br /&gt;
我们再来假设一下，程序要处理特殊的一类人：程序用户。用户有姓名，而且他们还有口令。我们可以对用户创建一个新的对象类型/接口，它可以声明说用户是带有口令的person。为此，要使用supports（支持）限定符： &lt;br /&gt;
&lt;br /&gt;
&amp;lt;vip&amp;gt;interface user supports person&lt;br /&gt;
predicates&lt;br /&gt;
    trySetPassword : (string Old, string New, string Confirm) determ.&lt;br /&gt;
    validatePassword : (string Password) determ.&lt;br /&gt;
end interface user&amp;lt;/vip&amp;gt;&lt;br /&gt;
&lt;br /&gt;
它说：user supports（支持） person ，这有两个功效： &lt;br /&gt;
&lt;br /&gt;
*这意味着 user 对象要提供在 person 接口中声明的谓词（即 getName 和 setName）&lt;br /&gt;
*这还意味着user类型的对象也是person类型的对象，因而也就可以用在需要person对象的关联中。假设我们有如下的user类：&lt;br /&gt;
 &lt;br /&gt;
&amp;lt;vip&amp;gt;class user : user&lt;br /&gt;
constructors&lt;br /&gt;
    new : (string Name, string Password).&lt;br /&gt;
end class user&amp;lt;/vip&amp;gt;&lt;br /&gt;
&lt;br /&gt;
那么，这个类的对象也可以被 mail::sendMessage 使用： &lt;br /&gt;
&lt;br /&gt;
&amp;lt;vip&amp;gt;goal&lt;br /&gt;
    P = user::new(&amp;quot;Benny&amp;quot;, &amp;quot;MyCatBobby&amp;quot;),&lt;br /&gt;
    mail::sendMessage(P, &amp;quot;Hi Benny, ...&amp;quot;).&amp;lt;/vip&amp;gt;&lt;br /&gt;
&lt;br /&gt;
一个接口可以支持若干个其它接口，这就是说：&lt;br /&gt;
&lt;br /&gt;
*该类型对象必须提供所支持接口中的所有谓词 &lt;br /&gt;
*该类型对象具有所有所支持接口的类型。&lt;br /&gt;
&lt;br /&gt;
一个接口也可以支持一个或多个自身支持其它接口的接口，如此等等。在这样的情况下： &lt;br /&gt;
&lt;br /&gt;
*该类型对象必须提供它所直接和间接支持接口的所有谓词 &lt;br /&gt;
*该类型对象具有所有直接和间接支持接口的类型。&lt;br /&gt;
&lt;br /&gt;
supports 限定符会产生一个亚层，我们称 user 是 person 的子类。 &lt;br /&gt;
&lt;br /&gt;
==对象：根对象 超类型==&lt;br /&gt;
&lt;br /&gt;
一个接口没有显式地支持任何其它接口时，隐含地意味支持接口object。object是一个隐含定义的接口，没有内容（也就是没有谓词）。任何对象都直接或间接地支持object接口，所以任何对象都具有object类型。因此，object是所有对象类型的超类。&lt;br /&gt;
&lt;br /&gt;
==继承==&lt;br /&gt;
&lt;br /&gt;
当实现user类时，当然想要利用已有的两个person类。假设我们想要user类与person类差不多，只不过是还需要处理口令。这样，我们可以让user类从person类中 inherit （继承）person那部分的实现。下面的代码就可以做到这个要求： &lt;br /&gt;
&lt;br /&gt;
&amp;lt;vip&amp;gt;implement user&lt;br /&gt;
    inherits&lt;br /&gt;
    person&lt;br /&gt;
 &lt;br /&gt;
facts&lt;br /&gt;
    password : string.&lt;br /&gt;
 &lt;br /&gt;
clauses&lt;br /&gt;
    new(Name, Password) :-&lt;br /&gt;
        person::new(Name),&lt;br /&gt;
        password := Password.&lt;br /&gt;
 &lt;br /&gt;
clauses&lt;br /&gt;
    trySetPassword(Old, New, Confirm) :-&lt;br /&gt;
        validatePassword(Old),&lt;br /&gt;
        New = Confirm,&lt;br /&gt;
        password := New.&lt;br /&gt;
 &lt;br /&gt;
clauses&lt;br /&gt;
    validatePassword(Password) :-&lt;br /&gt;
        password = Password.&lt;br /&gt;
end implement user&amp;lt;/vip&amp;gt;&lt;br /&gt;
&lt;br /&gt;
上面的实现说它 inherits person，如此一来，就会有如下效果：&lt;br /&gt;
&lt;br /&gt;
*每个构造出来的user对象都内含了person对象 &lt;br /&gt;
*user类可以直接由person类继承所有person接口的谓词。继承谓词时，并不是直接说它的实现，而是说要继承的实现所在的类。&lt;br /&gt;
 &lt;br /&gt;
The inheritance can to a certain extend be explained as syntactic sugaring. At least I could have achieved exactly the same effect with the following code (the clauses for the password predicates remains as above): &lt;br /&gt;
&lt;br /&gt;
&amp;lt;vip&amp;gt;implement user&lt;br /&gt;
facts&lt;br /&gt;
    person : person.&lt;br /&gt;
    password : string.&lt;br /&gt;
 &lt;br /&gt;
clauses&lt;br /&gt;
    new(Name, Password) :-&lt;br /&gt;
        person := person_class::new(Name),&lt;br /&gt;
        password := Password.&lt;br /&gt;
 &lt;br /&gt;
clauses&lt;br /&gt;
    getName() = person:getName().&lt;br /&gt;
 &lt;br /&gt;
clauses&lt;br /&gt;
    setName(Name) :- person:setName(Name).&lt;br /&gt;
 &lt;br /&gt;
    ...&lt;br /&gt;
end implement user_class&amp;lt;/vip&amp;gt;&lt;br /&gt;
&lt;br /&gt;
上面的代码，我们没有继承person类的什么东西，而是自行创建 person 对象并把它保存在事实变量中。也没有继承 getName 和 setName 的代码而是直接实现了这些谓词，它们只不过是把工作委托给了事实变量中的对象。带有关键字 delegate 的段可以用来便捷这样的委托。 &lt;br /&gt;
&lt;br /&gt;
这个代码功能上很相似，但还是有显著的差别： &lt;br /&gt;
&lt;br /&gt;
*首先，代码还是多写了些 &lt;br /&gt;
*person对象没有内含在user对象中，而是引用了它（还有，这里有两个内存分配块而不是一个）。&lt;br /&gt;
*在后面这个情况下，我们可以 动态地 改变事实变量中的值为其它的对象，这只需要给事实变量赋值为新的对象，比如，类personInDB的一个对象。要注意，第二种实现在调用过程中有间接的一层。Visual Prolog处理这样的间接关系是相当有效率的，不过它处理继承会更有效率。&lt;br /&gt;
 &lt;br /&gt;
Visual Prolog具有多重继承特性，也就是说，可以同时继承多个类。&lt;br /&gt;
&lt;br /&gt;
==小结==&lt;br /&gt;
上面，我们介绍了Visual Prolog中对象系统的基本概念。对象系统中还有其它一些有意思的特征，这里没有说到，比如：&lt;br /&gt;
&lt;br /&gt;
*对象可以在实现中进一步支持接口 &lt;br /&gt;
*用于内存回收的终结程序 &lt;br /&gt;
*对象谓词值，a seamless counterpart to C# delegates. &lt;br /&gt;
&lt;br /&gt;
==参考==&lt;br /&gt;
&lt;br /&gt;
[[Category:Tutorials]]&lt;/div&gt;</summary>
		<author><name>Yiding</name></author>
	</entry>
</feed>