Simula，一種編譯式的程式語言，由奧利 約翰達爾與克利斯登奈加特，在 1960 年代於挪威奧斯陸的，開發出來了 Simula I 與 Simula 67 兩代。它承繼了 ALGOL 60 作為基礎，被認為是第一個物件導向程式設計的程式語言。 Simula 67 介入了物件、類、子類（後來慣稱為子類繼承超類）、虛過程，還有協程、離散事件模擬和特徵性的垃圾收集。Simula 的影響經常被低估，Smalltalk、CLU、C、Object Pascal、Modula3、Java 和後來的很多程式語言，受到了 Simula 67 的啟發。BETA 是 Simula 的現代後繼者。 歷史 1957 年，克利斯登奈加特開始在的電腦上寫模擬器，為此他需要更強大的程式語言。1962 年 1 月，奧利 約翰達爾開始跟他合作，他們受到 ALGOL 60 的啟發。1962 年 5 月，發展出第一份模擬器程式語言提議，語言取名為 SIMULA，後改稱為 Simula I。此時，克利斯登奈加特受到邀請，去協助他們開發電腦。UNIVAC 軟體部門的主管，力邀克利斯登奈加特前往（IFIP）舉行的第二次國際會議上，發表了論文「SIMULA－擴充套件 ALGOL 到離散事件網路的描述」 。 1963 年 8 月，（NCC）購買到，在 UNIVAC 的合約同意下，奧利 約翰達爾在這臺電腦上安裝以凱斯西儲 1107 ALGOL 60 的編譯器來實作的 Simula I。1965 年 1 月，Simula I 終於可以在 UNIVAC 1107 上完全的運作。Simula I 在 1968 年被移植到了 B5500 電腦，以及後來蘇聯的電腦。 1965 年，東尼霍爾首次提出 記錄類（record class）構造的概念，1966 年，克利斯登奈加特與奧利 約翰達爾二人，將 Simula I 的具有 準並行 性質的 程序，擴充套件成了具有了記錄類性質的廣義程序，隨即改稱為 物件 。1967 年 5 月，奈加特和達爾在奧斯陸舉辦的 IFIP 工作小組論壇中，發表了關於類與子類宣告的論文，形成 Simula 67 的第一份定義檔案。 1968 年召開的會議，組成了 SIMULA 標準小組，並發表了第一份官方 Simula 標準檔案「SIMULA 67 通用基礎語言」。在 1960 年代後期和 1970 年代早期，Simula 67 主要實現於四個系統之上：的 UNIVAC ，挪威計算中心的 IBM System360 和，奧斯陸大學在聯合安裝的 CDC ，和（FOA）的 DEC TOPS10。 當前的 Simula 67 業界標準，是在 1986 年修訂的 標準 SIMULA，它在 1987 年被接受為瑞典國家標準。它有四個主要實現：、Lund Simula、GNU Cim 和 Portable Simula Revisited。 Simula 影響了 Smalltalk，和後來的面向物件程式語言。C 語言和 Java 語言的創始人，都認可自己受到了 Simula 的重要影響。 語法和語義 Simula 67 包含通用演算法語言 ALGOL 60 的多數特徵作為自己的子集，它是大小寫不敏感的。Simula 67 的中心概念是物件，物件是（selfcontained）的一段程式即一個塊例項，它擁有由一個類宣告定義的自己的區域性資料和行動（action）。類是一種過程，它有能力引起在它被呼叫後仍存活的一個塊例項，而這些例項就叫做這個類的物件。為了操縱物件和相互關聯物件，語言介入了連結串列處理設施。 Simula 67 為了將整個程式執行組織為：物件所屬的諸 行動階段 的一個序列，而將其所必需的基本功能特徵，包含在作為 系統類 的 環境類 之中。在環境類中有被稱為 標準系統類 的模擬器類 Simulation，它定義了充當系統時間軸的 定序集合（sequencing set）物件 SQS、程序類 Process 和事件通告類 EVENT_NOTICE，定序集合的成員是事件通告物件，它透過其 PROC 特性提及一個程序物件；事件通告表示了對應這個程序物件的下一個行動階段的一個事件，被排程在系統時間 EVTIME 時發生。 塊 塊是成序列的宣告，跟隨著成序列的語句，並被包圍在關鍵字 begin 和 end 之間。塊自身是一種語句，在 Simula 67 中，它包括子塊和有字首（prefixed）塊，在語法上，子塊就是無字首的 ALGOL 60 的塊，即匿名塊和過程主體。 宣告擔負定義在程式中用到的量（quantity）的特定屬性，並給它們關聯上識別符號，這包括：簡單變數、陣列、switch（標籤列表）、過程、類和外來宣告。塊中的每個語句，都可以是塊或複合語句。複合語句與塊相比在語法上沒有宣告。 所有的塊，自動地介入（nomenclature）的一個新的層級：在這個塊內出現的識別符號，可以透過合適的宣告，而被指定為區域性於所論及的這個塊；這個識別符號在這個塊裡面的所表示的實體，不存在於它的外面；這個識別符號在這個塊外面的所表示的任何實體，在這個塊裡面是不可見的；在 Simula 67 中，可透過連線或遠端訪問使它成為可見的。 除了表示標籤的識別符號之外，一個識別符號，如果出現在一個塊中，而且並非聲明於這個塊中，則它於這個塊。因為塊中的語句自身可以是一個塊，區域性和非區域性於一個塊的概念，必須遞迴地去理解。 塊是一種形式描述或模式，關乎的資料結構和關聯的演算法以及行動。當一個塊執行的時候，生成這個塊的一個動態例項。一個塊例項，可以被認為是它的形式描述的文字複本。在計算機中，一個塊例項可以採用某一種形式的記憶體區域，它包含需要的動態塊資訊，幷包括空間來持有區域性於這個塊的變數的內容。 塊的任何一個內部的塊，仍然是一個模式，但是在其中出現的識別符號，標定了區域性於在字面上外在包圍（textually enclosing）的塊例項的專案。於內部的塊的識別符號繫結，對這個內部的塊的任何隨後的動態例項，保持有效。 塊例項中的區域性變數，標識了分配給塊例項的記憶體片段。在進入一個塊之中的時候，任何區域性於這個塊即在其中宣告的變數，都會被初始化。區域性於一個塊的一個變數，是一個記憶體裝置，其內容依據這個變數的型別，要麼是一個值，要麼是一個引用。 值型別可特徵化為直接關聯著一個可能值的集合，即這個型別的 值範圍。引用概念，對應於一個名字或一個 指標 的直觀想法。在 Simula 67 中有兩種引用型別，物件引用型別和文字引用。對於值型別不關聯著引用概念。提供了引用值的機制，還反映了機器的定址可能性；在特定簡單情況下，一個引用可以被實現為一個儲存的值的記憶體地址。 過程 過程與塊相比，它有一個名字，可以在程式的一些不同地方提及，並且在呼叫時可以給出引數。過程和塊都不可能建立到它或它內部的引用；對於一個給定塊，有可能生成它的一些可以共存和互動的例項，例如遞迴過程的例項。 過程的引數傳送模態，除了有傳值呼叫和傳名呼叫，在 Simula 67 中，又增加了傳引用呼叫。過程的預設的傳送模態，在 Simula 67 中，對於值型別的引數是傳值呼叫，對於所有其他型別的引數是傳引用呼叫；故而在過程宣告的引數規定中，增加了以 name 為前導的名字部份，用來指定所述及的引數採用傳名呼叫。 在過程主體內傳名呼叫的形式引數的每次出現，都引起對實際引數的一次求值。在 Simula 67 中，這個求值發生在過程語句的上下文中，就是說不會出現識別符號衝突，因為過程主體和它的變數此時是不可見的。過程呼叫的執行，在有引數的情況下要經歷如下步驟：建立形式引數塊例項；求值對應於傳值呼叫或傳引用呼叫的實際引數，並將其結果賦值給形式引數塊例項的對應變數；過程主體被初始化並開始執行。 真正（proper）過程，不定義特定型別的函式指定式的值，在 Simula 67 中，它被稱為具有普遍（universal）型別，任何型別都從屬（subordinate）於普遍型別。 類與物件 類宣告定義一個程式（資料和行動）模式，而符合（conforming）這個模式的物件被稱為 屬於相同的類。不同於 Smalltalk 80 等面向物件程式語言，Simula 67 的類和後來的 Modula3 的物件型別，不進行與的區分。 對於一個給定物件，類宣告中形式引數、在虛擬部份中規定的虛擬量，和宣告為區域性於類主體（body）的量，叫做這個物件的特性（attribute）。一個特性的宣告或規定叫做特性定義。在 1986 年修訂的語言標準中，透過保護規定可以限制類特性識別符號的可見性。 類宣告中的形式引數，不適用傳名呼叫，這是為了保證實際引數在類所引起的物件存活期間不能消失。在規定部份中需要對每個形式引數進行規定，這些引數被當作區域性於類主體的變數。類主體通常是一個塊，即使它如語法形式所允許的那樣是塊以外的一個語句，也表現得如同一個塊。一個分裂（split）主體表現為一個塊，在其中符號 inner 表示一個虛設（dummy）語句。 Simula 67 的類主體中除了有定義特性的宣告，還可以有定義行動的語句。如果在一個類宣告中有行動定義，則符合這個模式的行動，可以由屬於這個類的所有物件執行。如果在類宣告中沒有指定行動，則定義了一類純資料結構，很多後來的面向物件程式語言就是這樣，將物件作為記錄或結構的擴充套件。例如： class Order number integer number begin integer numberOfUnits arrivalDate real processingTime end 屬於特定類的物件，透過物件表示式中的物件生成式 new 來生成，並製作出到它的引用。例如，想要多少就能生成多少屬於這個 Order 類的一個新物件： new Order 103 屬於一個物件的行動，可以都在就一個過程而言的一個序列中執行。這些行動，還可以作為一系列的獨立子序列或 行動階段（active phase）來執行。在一個給定物件的兩個行動階段之間，可以出現任何數目的其他物件的行動階段。 子類與類串接 一個類可以被用作到另一個類宣告的 字首，從而將字首所定義的性質，建造入這個新的類宣告定義的物件之中。具有字首類 C 和類識別符號 D 的一個類宣告，定義了類 C 的一個子類 D。屬於子類 D 的物件，由自身是類 C 的物件的 字首部份，和類 D 的類宣告主體所描述的 主體部份 組成。這兩部份串接而形成了一個複合物件，它可以用串接成的類宣告來正式的描述，串接的過程被認為先於程式執行而發生。 類只能在定義它的塊層級中用作字首。字首類自身也可以有字首。類不能出現在自己的字首序列中。子類被稱為內部（inner）於前綴類，而字首類被稱為外部（outer）於子類，但不可將子類稱為字首類的內部類。這不同於後來的面向物件程式語言中的稱謂：派生類 擴充套件 基礎類，或 子類 繼承 超類。例如： Order class SingleOrder begin real setupTime finishingTime weight end SingleOrder class Plate begin real length width end 屬於 Order 類的子類如 SingleOrder 類和 Plate 類的新物件，都含有 Order 類定義的資料，再加上在各種類宣告中定義的補充資料。例如，屬於 Plate 類的物件含有 Order 類、SingleOrder 類和 Plate 類定義的所有資料。 一個識別符號在一個塊中的出現，如果並未處在遠端識別符號之中或在有重新定義的內部的塊之中，則被稱為 未託付（uncommitted）出現。對於子類的宣告及其字首類串接成的類宣告，在區域性於子類的特性識別符號，和區域性於其字首類的特性識別符號，二者的未託付出現之間的可能衝突，將憑藉對涉及到的區域性於子類的特性識別符號的適合的系統性變更來避免，但是對應虛擬量的識別符號不變更。 對於字首類和子類宣告串接成的類宣告，它的形式引數列表，由字首類的形式引數列表，和附加的子類宣告的引數列表二者合併而成。它的值部份、規定部份和虛擬部份，是字首類和子類宣告相應各部份的並集。結果的虛擬部份不能包含某個識別符號的多於一次出現。 對於類主體，最初的 begin 和隨後的宣告被稱為 塊頭部，從第一個可執行語句直到 inner 之前的語句被稱為 初始運算，在 inner 之後的語句和最終的 end 被稱為 複合尾部。如果字首類主體是分裂主體，用字首類的塊頭部複本替代子類的塊頭部中的 begin，將字首類的初始運算複本插入到子類的塊頭部之後，用字首類的複合尾部複本替代子類的複合尾部中的 end。如果字首類主體不是分裂主體，它被解釋為如同將；inner 插入到最終的 end 之前。 設 Cn 是具有字首序列 C1 C2 Cn1 的一個類，這裡類 Ck k 1 2 n 的下標 k 叫做字首層級，X 是屬於類 Cn 的一個物件，則 X 是一個複合物件；非正式的說，串接機制有如下結果： 物件 X 擁有的特性集合，是在序列 C1 C2 Cn 中諸類所定義特性集合的並集。在類 Ck 1 k n 中定義的特性，被稱為定義在字首層級 k。 物件 X 擁有的 運算規則，由來自這些類主體的諸語句構成，它們所屬的字首層級遵循規定的次序。來自類 Ck 的語句，被稱為屬於物件 X 的字首層級 k。 在物件 X 的字首層級 k 的語句，能訪問在物件 X 的等於或外部於 k 的字首層級上定義的它的所有特性，但是如果外部的類 Ci i k 中存在衝突定義，則導致對應特性不可見而不能直接訪問。這些不可見特性仍有訪問方式，例如透過使用過程或 this Ci。 在物件 X 的字首層級 k 的語句，不能立即訪問在物件 X 的內部於 k 的字首層級上定義的它的那些特性，除非透過虛擬量。 在字首層級 k 的分裂主體中，符號 inner，表示物件 X 的屬於內部於 k 的字首層級的運算規則的諸語句，或者在 k n 時表示虛設語句。如果序列 C1 Cn1 都沒有分裂主體，則在物件 X 的運算規則中諸語句所屬的字首層級遵循遞增次序。 用作字首的系統類，與其字首鏈的所有的類一起，被當作聲明於最小的包圍其字面上出現的塊中。因此重新宣告可以出現在一個程式的內部的塊層級中。 有字首塊的一個例項，是由塊字首生成的一個單一的物件，與這個主體塊的例項，串接而成一個複合物件，其串接定義採用類似於類的串接規則。塊字首的類的形式引數，按塊字首的實際引數所示初始化。對有字首塊有兩個限制：一個類如果在其中透過使用 this 來引用類自身，則它作為塊字首是非法的。塊字首的類識別符號所提及的類，必須區域性於最小的包圍這個有字首塊的塊。 物件引用 當屬於各種類的很多物件，作為同一個程式的各個部份而共存的時候，需要能夠對個體物件指定名字，為此介入了叫做 引用 的新的基本型別；還要能相互關聯物件，比如透過二叉樹和各種其他型別的列表結構。Simula 67 將迴圈雙向連結串列叫做 集合，它將集合類 Simset 作為 標準系統類 介入為環境類的一部份。 對於某個類的一個物件，有一個唯一的關聯的 物件引用 標定這個物件，並且對於任何類 C，都有一個關聯的物件引用型別 ref C。這種型別的量，被稱為由類 C 限定；它的值，要麼是一個物件，要麼是表示 沒有物件 的特殊值 none。 限定（qualification）將值的範圍，限制至包括在限定類中的這些類的物件。不管何種限定，值的範圍都包括值 none。一個物件引用的限定，是一個類識別符號，它因此服從宣告的作用域和規則。限定關聯於所提及的類宣告所區域性於的那個塊的一個例項。這蘊涵著特定的關於限定有效性的檢查，不能單獨在程式正文的基礎上進行，因此這種測試必須在程式執行期間完成。 引用是有限定的，蘊涵著一個給定引用所提及的物件，只能屬於這個限定中提到的類，或屬於這個限定類的子類。如果一個物件引用型別的限定，是另一個物件引用型別的限定類的子類，則前者被稱為從屬於後者。例如： ref Order next previous 物件表示式是獲得對一個物件的引用的一種規則。物件表示式的值，是被引用的物件或 none。運算子 讀作 指稱（denote），它指示將一個引用，指派（assign）到處在 引用指派符 左側的引用型別的變數或過程識別符號。例如： next new Plate 50 previous next next none 而運算子 讀作 成為（become），指示將一個值，指派到處在賦值符左側的值型別的變數或過程識別符號，或者將一個文字值，指派到在賦值符左側者所引用的那個文字幀（frame）。 遠端訪問 一個物件的一個特定特性，由下列三項資訊來完全標定（identify）： 這個物件。 外部於或等於這個物件的類的一個類。 在這個類中或在屬於它的字首序列的任何類中定義的一個特性識別符號。 對於任何特性標定，第二項類資訊都是在字面上定義的，從而形成靜態繫結。屬於其他物件的特性，可以要麼單個的透過 遠端識別符號（點表示法），要麼成組的透過 連線（connection）機制，從其外面 遠端訪問 來引用和使用。 遠端識別符號的形式為：簡單物件表示式。特性識別符號，它可用作簡單變數、陣列變數、函式指定式（designator）和過程語句中的識別符號，這種點表示法給出對資訊的單獨片段的訪問，例如： if nextnumber previousnumber then 它將名為 next 的類 Order 的物件的特性 number，比較於名為 previous 的類 Order 的物件的特性 number。 成組訪問 可透過連線語句 inspect 來完成，例如： inspect next when Plate do begin end inspect new Plate 50 do begin end 在這裡的 begin 和 end 之間的語句中，next 引用的物件所屬的 Plate 類的所有資訊片段，都可以直接提及。 在 do 後面的語句，如果是塊以外的一個語句，它表現得也如同一個塊。連線語句進而表現得如同被叫做 連線塊 的第二個虛構（fictitious）的塊所包圍。連線機制的用途，是為在連線塊中的特定特性標定，提供物件資訊和在 when 子句中的類資訊的隱式定義。 設物件表示式求值為 X，在連線塊執行期間，稱物件 X 為 被連線上 了。連線塊有一個關聯的 塊限定，如果連線塊有 when 子句，它是前面的類識別符號，如果沒有 when 子句，它是前面的物件表示式的限定。 虛過程 虛擬（virtual）量，是在類宣告中由 virtual 前導的量，它有雙重用途： 允許在一個物件的一個字首層級上，訪問在內部字首層級上宣告的特性。 允許在一個字首層級上的特性重新定義，在外部字首層級上有效。 不同於一般的特性標定，虛過程形成 半動態繫結，在某種意義上是類似傳名呼叫的機制。這種機制不同於 Smalltalk 80 等面向物件程式語言中，上溯子類至超類的繼承鏈來找到最近的方法實現的那種動態繫結。 一個物件的一個虛擬量，要麼是 無匹配的 的，要麼被標定為具有一個 匹配 特性，它是在這個虛擬量的字首層級上或在內部字首層級上宣告的，其識別符號（coincide）於虛擬量的識別符號的一個特性。匹配特性必須與虛擬特性有相同的種類。在一個給定字首層級上的匹配量的型別，必須重合或從屬於這個虛擬規定的型別，和在任何外部字首層級上宣告的任何匹配量的型別。 在 1986 年修訂的語言標準中，虛過程量可選的可使用 procedure 過程識別符號 過程規定 方式來指定，即憑藉它的型別，並且如果它有形式引數，則還憑藉它們的型別、種類和傳送模態。含有過程規定 is 過程宣告 的虛過程量，只能由有相同型別的過程來匹配，並它與這個過程規定具有相同的過程頭部。 例如，下面實現散列表的 HashTable 類，聲明瞭整數型別的虛過程 hash 並隨即實現了它，又定義了要用到這個雜湊函式 hash 的查詢過程 lookup class HashTable n integer n virtual integer procedure hash begin integer procedure hash t text t begin end hash text array table 0 n1 integer procedure lookup t old name old Boolean old text t begin integer i istart Boolean entered i istart hash t while not entered do begin end lookup i end lookup end HashTable HashTable class ALGOL_hashing begin integer procedure hash t text t begin end hash end ALGOL_hashing 作為子類的 ALGOL_hashing 類和以 HashTable 類為字首的有字首塊，可以用自己的 hash 過程實現，替代在 HashTable 類中的實現。在子類的類主體和有字首塊的主體塊中，能獲得到過程 lookup，而它用到的過程 hash 是這裡提供的替代實現。 物件表示式 物件，具有型別 ref 限定。物件表示式的限定規則包括：物件生成式（generator）、區域性物件或限定物件，分別由跟隨符號 new、this 或 qua 的識別符號的類來限定（qualification）。 物件生成式，這裡標定了類 C，它涉及到屬於類 C 的物件的生成和執行。這個物件是類 C 的一個新例項。物件生成式的求值構成自如下行動： 生成這個物件，並且如果這個物件生成式有實際引數，則求值它們，將得到的這些值引用傳送給形式引數。 控制經過這個物件最初的 begin 進入其中，它籍此變成在 系附 狀態下執行。當所生成的物件執行了 detach 基本過程變為 脫離 狀態，或者經過這個物件最終的 end 退出而變為 終止 狀態，物件生成式的求值完成。 區域性物件，這裡的 C 是類識別符號。如果用在類 C 或 C 的任何子類的類主體中，或用在其塊限定為類 C 或 C 的一個子類的連線塊中，則這個物件表示式是有效的。在一個給定的上下文中，一個區域性物件的值，是一個物件或連線到一個物件，它是這個物件表示式在其中有效的、最小的在字面上外在包圍的塊例項；如果沒有這樣的塊，則這個物件表示式在這個上下文中是非法的。對於一個過程或類主體的例項（上下文），在字面上外在包圍（textually enclosing）意為包含它的宣告。 暫瞬限定 X qua C，這裡的 X 表示一個簡單的引用表示式，而 C 是類識別符號。設類 D 是物件 X 的限定，對於限定物件 X qua C，如果類 C 外部於或等於類 D，或者是 D 的一個子類，則這個物件表示式是合法的，否則是為非法。如果 X 的值是 none，或者是屬於外部於 C 的類的一個物件，則這個物件表示式求值形成一個執行時間錯誤；在其他情況下，X qua C 的值，就是 X 的值。對一個串接的類物件的暫瞬限定，限制或擴充套件它的特性透過檢視或遠端訪問的可見性。 物件關係表示式，使用運算子 is 和 in，來測試一個物件的類成員關係。關係，在 X 引用的是屬於類 C 的物件之時，值為 true，否則值為 false。關係，在 X 引用的是屬於類 C 的物件，或者 X 是內部於類 C 的類之時，值為 true，否則值為 false。 不同於算術關係表示式使用比較運算子 和 ，物件引用關係表示式，使用比較運算子 和 ，來比較引用，從而區別於對應的被引用的值。兩個物件引用 X 和 Y，在它們都引用相同的物件，或者它們都是 none 之時，被稱為是 的。關係 X Y，在這種情況下擁有的值為 true，否則值為 false。關係 X Y 的值，是 X Y 的值的否定。 作用域和可見性 不同於 ALGOL 60 規定了量的作用域與，在 Simula 67 中，一個識別符號定義及其關聯的識別符號，在其作用域與可見性之間需要做出區別。 作用域：一個識別符號定義的作用域，是它在其中可能有作用的那一部份程式正文。同一個識別符號，可以定義在程式的很多地方，因此可以關聯於不同的量。同一個識別符號的這些定義的作用域，因而可能有所重疊，例如在一個識別符號在內部塊中被重新宣告的情況下。 ：一個識別符號定義，如果它所關聯的識別符號，在程式的給定點上能夠提及到這個定義所宣告的量，則它被稱為在這個點上是的。在給定識別符號於此可見的程式正文的一個特定點上，最多隻能有一個定義關聯於這個識別符號，例如在重新宣告的情況下，在它們作用域的並集內任何給定點上，只有一個定義是可見的。 一個識別符號定義的區域性塊，是在字面上最近的包圍塊，即子塊、字首塊、過程主體或類主體，還包括圍繞 for 語句的受控語句、過程宣告、類宣告和連線塊等的虛構塊。這個識別符號和它的定義，被稱為區域性於這個塊。 識別符號定義，只在它們的作用域內是可見的。一個特定定義的可見性，在它的作用域內可以受到下列限制： 在一個識別符號定義的區域性塊所包圍的某個構造內，出現的具有相同識別符號的識別符號定義，是這個識別符號的重新定義。在它們共同的作用域內，只有最內部的重新定義是可見的。 一個重新定義，出現在類的某個內部字首層級。 遠端訪問，可以導致某些識別符號定義在檢視塊或點表示法內變成不可見的。 使用 this 或 qua，可以導致一個或多個重新定義被暫時停止。 在這個識別符號定義所區域性於的類宣告中，這個識別符號出現在由 hidden 及或 protected 前導的保護部份中。 一個識別符號的重新定義，不允許出現在它的區域性塊的頭部，這禁止了在同一個塊中出現相同識別符號的兩個定義。 塊例項 一個的各個組成部份，都是塊即子塊、有字首塊、連線塊和類主體的動態例項。一個塊例項，被稱為 區域性於 直接包含它的描述正文的那個塊例項。例如一個給定類的例項，區域性於包含這個類宣告的塊例項。最外層塊的例項不區域性於塊例項。 在任何時間，程式順序控制（Program Sequence Control），首字母簡寫為 PSC，參照在一個塊例項中當前被執行的程式點；形象的說，PSC 定位 至這個程式點，並被這個塊例項所 包含。進入任何塊，都涉及到生成這個塊的一個例項，於是 PSC 進入這個塊例項，到達它的第一個可執行語句上。 一個塊例項在任何時間，都是處在四種執行之一：系附（attached）、脫離（detached）、恢復（resumed）或終止（terminated）。沒有在字面上給出字首的任何類，都被定義為字首了一個虛構（fictitious）的類，它只有一個特性即 detach 過程，因此所有類物件或有字首塊的例項，都擁有 detach 過程。在環境類 ENVIRONMENT 中，還定義了用於排程的 call 過程和 resume 過程。 一個非類塊例項，總是在系附狀態下，這個例項被稱為系附到了導致它生成的那個塊上。因此一個過程體的例項，系附到包含對應函式指定式或過程語句的塊例項上。非類、非過程塊例項，系附到它所區域性的塊例項。在 PSC 到達非類塊例項的最終的 end 的時候，PSC 返回到緊隨導致這個塊例項生成的語句或表示式的程式點。 一個物件，最初是在系附狀態下，並被稱為系附到包含對應物件生成語句的那個塊例項上。一個物件，可以透過執行 detach 過程，進入脫離狀態。透過執行 call 過程，可以使一個脫離狀態的物件重新進入系附狀態，它藉此變為系附到包含這個呼叫語句的那個塊例項上。透過執行 resume 過程，可以使一個脫離狀態的物件進入恢復狀態。不使用 detach、call 或 resume 過程的一個程式執行，是一個簡單的系附狀態的塊的巢狀結構。 當 PSC 透過一個物件的最終 end，或透過 goto 語句離開它的時候，這個物件進入終止狀態。沒有塊例項系附到一個終止狀態的類物件上。終止狀態的物件，仍作為一個數據項而存在，它可以透過針對這個物件的包括過程和函式特性的這些特性的遠端標定來引用。 每當一個塊例項不復存在，區域性於或系附於它的所有塊例項也不復存在。一個物件的動態作用域，因而受限於它的類宣告的作用域。在 Simula 67 最初標準中曾提到過，語言實現可以使用垃圾回收技術，來進一步縮減一個物件的有效壽命的跨度。一個數組宣告的動態作用域，可以擴充套件超出包含這個宣告的塊例項的作用域，因為傳引用呼叫引數傳送模態適用於陣列。 準並行系統 一個準並行系統，由 構件（component）構成。構件是塊例項組成的巢狀結構，其中標定（identify）這個構件的那個塊例項，叫做 構件頭領。在每個系統中，構件中總是有一個被稱呼為 主構件，在 Simula 67 最初標準中它叫做 主程式，其他構件叫做 物件構件。 構件的定序（sequencing），由 detach、call 和 resume 過程支配。detach 過程針對隱式指定的一個物件進行操作，而 call 和 resume 過程顯式指定所操作的物件。 一個準並行系統，由包含區域性的類宣告的一個子塊或有字首塊的任何例項所標定。標定了一個系統的塊例項，叫做 系統頭領。一個系統的主構件的頭領（head），（coincide）於系統頭領。最外層的標定了一個系統的塊例項，被稱為 最外層系統。 一個系統的主構件的頭領，總是處在系附狀態。一個系統的物件構件的頭領，確切的就是區域性於系統頭領的那些脫離狀態的或恢復狀態的物件。在任何時間，在一個系統的構件之中，有確切的一個構件被稱為 生效（operative）的。不生效的構件，有關聯的 重新啟用點，它標定在這個構件被啟用（activate）時，要在它那裡繼續執行的程式點。一個物件構件是生效的，當且僅當這個構件的頭領處在恢復狀態。 稱謂一個塊例項 P 被一個塊例項 X 動態包圍，當且僅當存在一個塊例項序列：P Z0 Z1 Zn1 Zn X n 0，使得對於 i 1 2 n 有著：Zi1 系附到 Zi；或者 Zi1 是一個恢復狀態的物件，它關聯的系統頭領系附到 Zi。終止狀態和脫離狀態的物件，不被除了自身之外的塊例項動態包圍。 將當前包含 PSC 的塊例項動態包圍起來的塊例項鏈，叫做 執行鏈。在執行鏈上的塊例項，被稱為是 執行（operating）的，最外層的塊例項總是執行的。一個構件只要其頭領是執行的它就是執行的。 一個系統如果有一個構件是執行的，它就是執行的；在任何時間，一個系統最多有一個構件是執行的；執行的系統的頭領，可以是不執行的。一個執行的構件總是生效的；如果一個系統的生效構件是不執行的，則這個系統也是不執行的。在不執行的系統中的生效的構件，是當這個系統成為不執行的時候在執行的構件，當這個系統再次成為執行的時候它將仍是執行的。 對於一個不生效的構件 C，設它的頭領是 X，如果一個塊例項 P 包含了它的重新啟用點，則 P 被 X 動態包圍，並且 P 除了自身之外不動態包圍塊例項。由構件頭領 X 動態包圍的這個塊例項序列，被稱為構件 C 的 重新啟用鏈。除了 X 之外，這個鏈上的所有構件頭領，標定了生效而不執行的構件。在構件 C 成為執行的時候，在它的重新啟用鏈上所有塊也成為執行的。 除了系統構件，程式執行還可以包含不屬於特定系統的 獨立物件構件。任何這種構件的頭領，都是一個脫離狀態的物件，它區域性於一個類物件或一個過程主體例項，也就是說不區域性於某個系統頭領。根據定義，獨立構件總是不生效的，只能對它執行 call 過程。 協程和生成器 準並行系統的 detachresume 機制，是一種協程。在 Simula 67 最初標準中，沒有恢復狀態，並且沒有規定 call 過程，但 call 過程通常會出現在當時的語言實現中。detachcall 機制，相當於現在稱為生成器的 半協程，而最初標準中的 resume 過程可理解為 detach 過程與 call 過程的組合。1986 年修訂的語言標準，增補定義了 call 過程，新增了恢復狀態，並且重新定義了 resume 過程，它不可再理解為 detach 過程與 call 過程的組合。 準並行系統，被創建於進入包含區域性的類宣告的一個子塊或有字首塊的時候，藉此生成的例項成為這個新系統的頭領。初始時，這個主構件是生效的，並且是這個系統唯一的構件。 建立一個物件構件，要透過針對一個系附狀態的物件，執行 detach 過程，藉此 PSC 返回到這個物件系附到的那個塊例項。這個物件進入脫離狀態，併成為一個新的不生效的構件的頭領，這個構件的重新啟用點被定位到緊後於這個 detach 過程呼叫。如果這個物件區域性於一個系統頭領，則這個新的構件成為這個關聯的系統的成員。 透過 detach 和 call 過程，可以形成 半對稱定序，這隻涉及到物件構件，而不區分它們是屬於系統的構件還是獨立的構件。 對於一個不生效的物件構件，透過針對它的脫離狀態的頭領，執行一個 call 過程，可以重新啟用這個構件，藉此 PSC 移動到它的重新啟用點上。這個頭領重新進入系附狀態，並變成系附到包含這個 call 過程呼叫的塊例項上。這個構件正式的失去了本身（作為構件）的狀態。 透過 detach 和 resume 過程，可以形成 對稱構件定序，這隻涉及到屬於一個準並行系統的那些構件。對立於半對稱定序中的 呼叫者 與它的 被呼叫者，在對稱構件定序中的 恢復者 與它的 被恢復者，具有完全的對稱聯絡。 對於這個系統的一個不生效的物件構件，透過針對它的脫離狀態的頭領，執行一個 resume 過程，可以重新啟用這個構件，藉此 PSC 移動到它的重新啟用點上；這個構件的頭領進入恢復狀態，而這個構件變成生效的。這個系統以前生效的構件變成不生效的，並且它重新啟用點被定位到緊後於這個 resume 過程呼叫；如果這個構件是一個物件構件，則它的頭領進入脫離狀態。 對於當前生效的物件構件，透過針它的恢復狀態的頭領，執行一個 detach 過程呼叫，這個系統的主構件重獲生效的狀態，藉此 PSC 移動回到主構件的重新啟用點上。以前生效的構件變成不生效的，並且它重新啟用點被定位到緊後於這個 detach 過程呼叫。這個構件的頭領進入脫離狀態。 PSC 經過一個類物件的最終 end 的效果，除了使這個物件成為終止狀態，而非脫離狀態之外，相同於針對這個物件執行 detach 過程的效果。其結果是它不會得到重新啟用點，並且在它已經擁有作為構件頭領的狀態時，失去這種狀態。 程式範例 Hello World Simula 67 下的經典 Hello World 範例： begin outtext Hello World outimage end outtext 過程將字串輸出到緩衝區，而 outimage 過程將緩衝區內容輸出到標準檔案，二者都定義在輸出檔案類 OutFile 中，而它是檔案類 File 的子類。 二叉樹 下面例子中的 Tree 類，是二叉樹資料結構實現： class Tree val integer val begin ref Tree left right procedure insert x integer x begin if x val then begin if left none then left new Tree x else leftinsert x end else if right none then right new Tree x else rightinsert x end insert ref Tree procedure find x integer x begin if x val then this Tree else if x val then if left none then none else leftfind x else if right none then none else rightfind x end find end Tree 在 find 過程的主體中出現了表示式，它產生的值所引用的是當前節點。這裡透過函式指定式 Xfind x，來呼叫物件 X 的 find 過程，如果 Xval x，則這個函式的結果是到 X 自身的引用值。 協程 Simula 67 標準透過如下例項來詮釋叫做 準並行系統 的協程機制： begin comment 系統 S1 ref C1 X1 class C1 begin procedure P1 detach P1 end C1 ref C2 X2 class C2 begin procedure P2 begin detach 可嘗試 detach 或 resume X1 end P2 begin comment 系統 S2 ref C3 X3 class C3 begin detach P2 end C3 X3 new C3 resume X3 end S2 end C2 X1 new C1 X2 new C2 call X2 可嘗試 resume X2 end S1 這個例子程式中，有兩個準並行系統 S1 和 S2。系統 S1 是對應最外層子塊的最外層系統，它包含了兩個類宣告 C1 和 C2。系統 S2 對應於類 C2 的類主體中的匿名塊，它包含了一個類宣告 C3。 在 PSC 進入最外層子塊開始處，產生系統 S1 的系統頭領，到達第 28 行的系統 S1 主構件的第一個可執行語句，開始生成物件 X1，進入類 C1，PSC 到達第 7 行的類主體的第一個可執行語句，呼叫了類 C1 的特性過程 P1，進入第 6 行的過程體的第一個可執行語句，這時的狀況是： S1 X1 P1 PSC 這裡方括號表示系統頭領，圓括號表示其他種類的塊例項，左向箭頭表示系附，使用粗體表示這個塊例項執行了物件生成式。執行第 6 行的 detach 語句後，物件構件頭領 X1 進入脫離狀態，儲存 X1 的重新啟用點為第 6 行 P1 過程體結束，回溯到第 28 行物件產生式結束，系統 S1 的物件 X1 生成完畢，這時的情況是： S1 PSC X1 P1 X1 重新啟用點 這裡的豎槓將物件構件頭領列為一個系統的成員。PSC 到達系統 S1 主構件第 29 行，開始生成物件 X2，進入類 C2，PSC 到達第 17 行的類主體中匿名塊開始處，進入這個子塊產生系統 S2 的系統頭領，PSC 到達第 24 行的系統 S2 主構件的第一個可執行語句，開始生成物件 X3，進入類 C3，PSC 到達第 20 行類主體開始處，這時的情況是： S1 X2 S2 X3 PSC X1 P1 X1 重新啟用點 執行第 21 行類主體的第一個可執行語句 detach 後，物件構件頭領 X3 進入脫離狀態，儲存 X3 的重新啟用點為第 22 行，回溯到第 24 行物件產生式結束，系統 S2 的物件 X3 生成完畢，這時的情況是： S1 X2 S2 PSC X3 X3 重新啟用點 X1 P1 X1 重新啟用點 PSC 到達系統 S2 主構件的第 25 行，執行 resume X3 語句後，儲存系統 S2 主構件的重新啟用點為第 26 行，物件構件頭領 X3 進入恢復狀態，PSC 恢復到第 22 行的物件 X3 的類主體之中，這時的情況是： S1 X2 S2 S2 重新啟用點 X3 PSC X1 P1 X1 重新啟用點 這裡的下劃線指示這個塊例項處在恢復狀態。執行第 22 行的類 C2 的特性過程 P2，到達在第 14 行的過程體的第一個可執行語句，這時的情況如下，並標記為 狀況 A： 狀況 A S1 X2 S2 S2 重新啟用點 X3 P2 PSC X1 P1 X1 重新啟用點 執行在第 14 行 P2 過程體的 detach 語句後，物件構件頭領 X2 進入脫離狀態，儲存 X2 的重新啟用點為第 15 行，回溯到第 29 行物件產生式結束，系統 S1 的物件 X2 生成完畢，這時的情況如下，並標記為 狀況 B： ！狀況 B S1 PSC X1 P1 X1 重新啟用點 X2 S2 S2 重新啟用點 X3 P2 X2 重新啟用點 注意物件 X3 仍是系統 S2 的生效構件，它並沒有自己的重新啟用點。序列 P2 X3 X2 是 X2 的重新啟用鏈，這裡的 X3 是恢復狀態，而它的系統頭領 S2 系附到了 X2。 PSC 進入系統 S1 主構件第 30 行，執行 call X2 語句後，物件構件頭領 X2 進入系附狀態，PSC 恢復為第 15 行的 P2 過程體之中，這時的情況重現為前面的 狀況 A（S1 不加粗體）。 如果將系統 S1 主構件中第 30 行改寫為一個 resume X2，執行後物件構件頭領 X2 進入恢復狀態，儲存系統 S1 主構件的重新啟用點為第 31 行，PSC 恢復為第 15 行的 P2 過程體之中，會出現如下情況： S1 S1 重新啟用點 X1 P1 X1 重新啟用點 X2 S2 S2 重新啟用點 X3 P2 PSC 序列 P2 X3 X2 是 X2 的執行鏈。 如果將 P2 過程體中第 15 行的註釋替換為一個 detach 語句，執行後物件構件頭領 X2 進入脫離狀態，儲存 X2 的重新啟用點是第 16 行，PSC 恢復到第 31 行的系統 S1 主構件之中，這時的情況重現為前面的 狀況 B。 如果將 P2 中第 15 行的註釋替換為一個 resume X1 語句，執行後物件構件頭領 X2 進入脫離狀態，物件構件頭領 X1 進入恢復狀態，儲存 X2 的重新啟用點為第 16 行，PSC 恢復到第 6 行的 P1 過程體的過程結束，會出現如下情況： S1 S1 重新啟用點 X1 P1 PSC X2 S2 S2 重新啟用點 X3 P2 X2 重新啟用點 抽象類 下面例子中，定義了一個字形類 Glyph，它是抽象基礎類，並且有二個實現子類：字元類 Char 和類 Line： begin class Glyph virtual procedure print is procedure print begin end Glyph class Char c character c begin procedure print outchar c end Glyph class Line cs ref Glyph array cs begin procedure print begin integer i for i 1 step 1 until upperbound cs 1 do cs iprint outimage end end ref Glyph rg ref Glyph array rgs 1 4 rgs 1 new Char A rgs 2 new Char b rgs 3 new Char b rgs 4 new Char a rg new Line rgs rgprint end 這裡的虛過程量 print 具有過程規定 is procedure print，它匹配既沒有形式引數也沒有結果值的 print 過程，如果不加以這種過程規定，則它可以匹配具有任何形式引數和任何結果值的 print 過程。在 Simula 67 中，沒有不可以例項化帶有純虛過程類的特定限制，因而缺乏真正的抽象類的概念，所有類都可以被例項化，但是呼叫純虛過程會產生執行時間錯誤。 模擬器 在下面的離散事件模擬例子中，Sam、Sally 和 Andy 正在逛商店買衣服，他們必須共享一個試衣間。他們每人只能瀏覽商店大約 12 分鐘，並接著獨佔的使用試衣間大約 3 分鐘，每個行動都服從正態分佈，他們的試衣間經歷被模擬如下： Simulation begin class FittingRoom begin ref Head door Boolean inUse procedure request begin if inUse then begin wait door doorfirstout end inUse true end procedure leave begin inUse false activate doorfirst end door new Head end procedure report message text message begin outfix time 2 0 outtext message outimage end Process class Person pname text pname begin while true do begin hold normal 12 4 u report pname 要求用試衣間 fittingroom1request report pname 已進入試衣間 hold Normal 3 1 u fittingroom1leave report pname 已離開試衣間 end end integer u ref FittingRoom fittingRoom1 fittingRoom1 new FittingRoom activate new Person Sam activate new Person Sally activate new Person Andy hold 100 end 主程式是字首著模擬器類 Simulation 的有字首塊。模擬器類可在任何塊上使用，而且模擬器甚至可以巢狀，比如在模擬某人做模擬的時候。時間過程 time、等待過程 wait、保持過程 hold 和啟用過程 ACTIVAT，定義在 Simulation 類之中。 程序類 Process 是 Simulation 類的巢狀類。啟用語句 activate，只有處在 Simulation 類所包含的類的物件之中，或處在其字首部份是這種物件的有字首塊之中，才是有效的。啟用語句的作用，被定義為得到呼叫啟用過程 ACTIVAT 的那種效果。 集合類 Simset 是 Simulation 類的字首類，其中定義了三個巢狀類：表示集合整體的 Head 類，表示集合元素的 Link 類，和二者的字首類連結串列類 Linkage。首位過程 first，定義在 Head 類中；退出過程 out 和在等待過程 wait 中用到的進入過程 into，定義在 Link 類中。 在試衣間類 FittingRoom 中，為了讓人們排隊等待訪問試衣間，使用了門物件 door，它是佇列類即 Head 類的一個物件。試衣間類定義了兩個過程：要求過程 request：如果試衣間中正有人使用，則他必須等待於門佇列之中，即 wait door；當他可以使用試衣間之時，相應的從門佇列中移除自己，即 doorfirstout。離開過程 leave：如果門佇列中有人等待的話，放行其中第一個人，即 activate doorfirst。 個人類 Person 是 Process 類的子類，它的行動是瀏覽商店和在試衣間試衣，使用保持過程 hold 來描述其所用時間，並呼叫對應的試衣間物件的過程來要求和離開試衣間。正態分佈的隨機抽籤過程 normal，定義在環境類 ENVIRONMENT 中，它的最後的引數，必須是指定一個偽隨機數串流的一個整數。 主程式是程序類 Process 的子類 MAIN_PROGRAM 類的物件。它建立 FittingRoom 類的例項 fittingRoom1 物件，接著建立並激活 Person 類的三個物件，從而將他們三人放置入事件佇列之中，主程式在終止前保持 100 分鐘的模擬時間。 參見 面向物件程式設計 註釋 延伸閱讀 外部連結 S Category 基於類的程式語言 Category 模擬器程式語言 CategoryALGOL 程式語言家族