Ada有一個叫做 "受保護的型別 "的結構,在這個結構中,你有一個變數的集合和與一個型別相關的子程式,并且這些子程式有隱式同步。這些型別可以被實體化,每個實體都有自己的記憶體,變數就住在那里。這看起來很像主流 OOP 語言(如 C 和 Java)中的類/物件二元性,除去繼承性,再加上強制性的隱式同步。
是否存在與此結構相當的、去掉同步的結構?如果沒有,那么這種設計選擇背后的理由是什么呢?
說得很清楚,我知道 Ada 支持不同風格的 OOP,而沒有任何形式的同步。我的問題是關于我提到的特定的 OOP 風格--因為它是主流語言中最常見的風格之一,而且確實也以某種形式存在于 Ada 中。
為了進一步澄清這個被有意(和被誤導)留下的開放式問題,我知道答案是 "包"。但是,請考慮以下情況:
- 我們有一些包,這些包是我們自己的。
- 我們有包,它是包含變數和子程式的單元,其中可以創建多個實體 。
- 我們有型別,它是內置型別的列舉或投影/模型(我知道這是一個非常近似的定義,具體細節在這里并不重要)
- 我們有保護型別,它是內置型別的列舉或投影/模型(我知道這是一個非常近似的定義,具體細節在這里并不重要) 我們有保護型別,它是......包含變數和子程式的單元,其中可以創建多個實體。此外,它們還有同步功能。
這就引出了一個問題:為什么是 "保護型別 "而不是 "保護包"?這個想法是本問題的起源。
uj5u.com熱心網友回復:
OOP是編程中的一組概念,不依賴特定的語法。根據Ada 95的理由:"Ada 95中的型別擴展是建立在現有的Ada 83派生型別的概念之上的。在Ada 83中,派生型別繼承了其父類的操作,并可以添加新的操作;但是,不可能向該型別添加新的組件。因此,整個機制在某種程度上是靜態的。相比之下,在Ada 95中,派生型別也可以被擴展以添加新的組件。
在Ada中,一個型別就是一個型別,與它是否提供OOP功能無關。Ada 95在Ada 83型別已經提供的其他POO特性之上提供了擴展。這樣做的好處是,如果你以后需要型別擴展,你可以很容易地把一個非標記的型別變成一個標記的型別,而不影響該型別的當前使用。這也避免了在OOP語法中引入隱藏的特征,比如朋友類(共享包的型別)、靜態成員(全域包變數)、隱含的this,或者在方法的末尾表示this物件未被修改的const等等。
為什么受保護的型別不遵循這種模式?他們可能遵循Ada 83任務型別的模式,但后者沒有private部分,所以仍然是不一致的。設計者可能選擇了任務型別的語法作為靈感,但為了提高效率而增加了私有部分(這是主要的關注點:"受保護的型別允許更有效地實作共享資料訪問的標準問題")。
uj5u.com熱心網友回復:
所以這是對這個問題標題的回答。 "在Ada中,與受保護型別相對應的非同步型別是什么?"
我添加這個主要是為了讓搜索這個問題的人尋找這個主題的標題問題的答案。
以一個簡單的保護型別為例:
protected typeMy_Type is
procedure Set_Value(Value : Integer);
function Get_Value return Integer;
private
The_Value : Integer := 0;
end My_Type;
protected body My_Type is
程式 Set_Value(Value : Integer) is
begin
The_Value := Value。
end Set_Value。
function Get_Value return Integer is
begin
return The_Value;
end Get_Value。
end My_Type。
等效的非同步版本是在一個包內使用一個記錄型別(如果你想進行型別擴展,則使用一個有標簽的記錄),并對該型別進行操作:
package My_Types is
-- 用于 型別擴展使用。
-- type My_Type is tagged private;
type My_Type is private;
procedure Set_Value(Self : in out My_Type; Value : Integer);
function Get_Value(Self : My_Type) return Integer;
private
-- 用于 型別擴展使用。
-- type My_Type is tagged record
型別 My_Type 是 record
The_Value : Integer := 0;
end record。
end My_Types;
包體 My_Types 是
procedure Set_Value(Self : in out My_Type; Value : Integer) is
begin
Self.The_Value := Value。
end Set_Value;
function Get_Value(Self : My_Type) return Integer is
begin
return Self.The_Value;
end Get_Value。
-- 替代語法。
-- function Get_Value(Self : My_Type) return Integer is (Self. The_Value);
end My_Types;
在一個包內宣告的操作,如果在該型別被凍結之前對該包中的一個型別進行操作,則"關聯"到該型別(Ada稱它們為原始操作)。 這包括回傳這些型別的函式。
對于 "為什么 "每個布局的選擇不同,我真的不知道。 看看以下頁面的底部,并查看 ARG 的所有評論/郵件/討論(最初的鏈接歸功于 Simon Wright)可能會有所幫助:
<http://archive.adaic.com/standards/ada95.html
如果讓我猜測,在沒有完全讀完西蒙指給我的那些章節的情況下(我會把它們全部讀完),我敢打賭,這與記錄在保護型別存在之前就已經存在,而保護型別被認為更像是任務模型的延伸,所以他們為保護型別迭代了任務型別布局。 我所讀到的一些內容(這里和這里)已經讓我相信他們在嘗試將保護型別布置得更像記錄時遇到了一些現有的問題(無論是技術上還是理念上)。
請注意,受保護的型別并不像大多數程式員所期望的那樣提供全套的 "資訊隱藏 "功能,例如公共與私有成員變數(對于受保護的型別來說只有私有)。
感謝Simon Wright為我提供的鏈接
。uj5u.com熱心網友回復:
在Ada中,定義一個完整型別(資料 操作)的標準方式是使用一個包含型別宣告(通常是私有的)和該型別的子程式的包。
一般來說,封裝和資訊隱藏(包)與Ada中的型別和子程式是正交的。在許多常用的語言中,封裝和資訊隱藏只由類結構提供。
uj5u.com熱心網友回復:
這是一個有點漫無邊際的話題......
如果你有一個受保護的包,其內容的哪些部分將被同步化?任何變數、規格或主體、任何型別、子包?而且,為了能夠創建包的多個實體,它必須是generic。那么你怎么能在一條記錄中創建一個實體呢?我認為它應該是一個型別。
據我所知,在C 中并沒有與包平行的東西,所以你不得不說保護類Foo ...,這似乎很難與保護型別區分。
考慮到包已經封裝了其他的東西,我想設計團隊可以采用類似于
的方式。型別P是記錄
...
結束記錄。
pragma Protected (P);
在這里,P的原始操作將被同步,但是你會遇到清晰度的問題(原始性容易出錯)和可見性的問題(你真的不希望P的任何組件可以從外部訪問)。我們為entry操作使用什么語法?受保護的型別似乎是一個合理的折衷方案。
uj5u.com熱心網友回復:
是否有一個與此結構等價的東西,去掉了同步? 如果沒有,這種設計選擇背后的理由是什么?
好吧,其他答案真的很不錯,但這里的答案很簡單。
Ada 將"型別"定義為一組值和對這些值的一組操作;"子型別"的概念也同樣被定義為一個對其值具有額外(可能為空)約束的型別。- 這導致了"子型別Natural是Integer 0...Integer'Last;"的能力--在Ada 83中,沒有辦法向一個型別添加值,但是有was型別衍生,你可以 "繼承 "一個型別,可能添加其他操作和/或改變表示項。(因此你可以有"Type Native_Data is array(1..10, 1..200) of Integer;"和"Type External_Data is new Native_Data;"以及"For External_Data'Convention use Fortran;"1并通過轉換在本地和外部格式之間轉換。Data:= Native_Data( From_Disk(File => "Import.dat") )。)
因此,Ada95建立在型別衍生之上,允許更多的值,這些值是型別擴展(以及更多操作)。- Ada95還將庫/編譯單元的結構從 "扁平 "概念擴展為分層結構,但基本的組織單位是(現在仍然是)package。
現在,我們來到了保護型別,保護型別是同步型別,資料被封裝到結構體中,并通過訪問器和突變器進行操作--這種結構體幾乎是包和任務的私生子:它的結構令人想起包,并具有類似佇列的訪問(條目、函式。
那么,什么是任務?
那么,什么是沒有同步的保護型別呢? 很簡單,一個普通的型別。
這引出了一個問題:為什么是 "受保護型別 "而不是 "受保護包"? 包"?
雖然我相信上面提供的資訊足以讓你弄清楚,但簡單的答案是:
包是真正的介面(在這里是指介面)。 包實際上是介面(一般的概念,而不是關鍵字/標簽型別的概念)和命名空間:它們宣告了公共視圖,也隔離了私有實作,以及封裝了其中的事物的范圍。
因此,"Protected Package"本質上是 "帶有命名空間 "的保護型別--因此是一個真正多余的結構,更不用說保護型別的動機之一是能夠從任務中洗掉同步所需的主動控制線。所有這些都可以由編譯器在訪問周圍插入適當的佇列/簿記來處理,而不需要任務所需要的任何復雜性(和時間/調度強加)--所以 "受保護包 "必須有特殊的規則,要么不允許Task,要么需要一些特殊的形式,這將增加編譯器的復雜性。
1 - Fortran對其多維陣列使用列主排序,Ada使用行主排序[我不記得LRM是否要求這樣做];這個 "技巧 "允許你讓編譯器處理 "轉換位置",以及使用型別系統來追蹤哪個是哪個。(你也可以在協議中使用這個方法,比如網路格式與本地格式的對比。)
。轉載請註明出處,本文鏈接:https://www.uj5u.com/shujuku/329340.html
標籤:
上一篇:無法在回圈單鏈表中插入節點
下一篇:用條件查詢多對多
