在Ada中使用私有类型创建私有int 我试图在艾达中实现一个私有类型,就像它在java或C++中使用一样。例如,我想在Ada中有一个“private int”
正如我在这里发现的,我必须在包体中实现我的变量。所以我试着实现这个,就像示例中描述的那样 我的问题是,我无法创建用于创建对象的create函数并设置值。我的第二个问题是,我想要这样的孩子。这些子类应该有一个Create函数,用于设置主类和子类的值 这是我不工作的代码。我补充了一些不起作用的观点在Ada中使用私有类型创建私有int 我试图在艾达中实现一个私有类型,就像它在java或C++中使用一样。例如,我想在Ada中有一个“private int”,ada,Ada,正如我在这里发现的,我必须在包体中实现我的变量。所以我试着实现这个,就像示例中描述的那样 我的问题是,我无法创建用于创建对象的create函数并设置值。我的第二个问题是,我想要这样的孩子。这些子类应该有一个Create函数,用于设置主类和子类的值 这是我不工作的代码。我补充了一些不起作用的观点 private with Ada.Finalization; package MasterClass is type MasterC is tagged private; type
private with Ada.Finalization;
package MasterClass is
type MasterC is tagged private;
type MasterC_Class_Ref is access all MasterC'Class;
procedure printNumObjects;
procedure do( This : in MasterC );
function Make (f1, f2 : Float) return MasterC;
function getVar(This : MasterC) return float;
private
type Private_Part; -- declaration stub
type Private_Part_Pointer is access Private_Part;
type Private_Component is new Ada.Finalization.Controlled with record
P: Private_Part_Pointer;
end record;
overriding procedure Initialize (X: in out Private_Component);
overriding procedure Adjust (X: in out Private_Component);
overriding procedure Finalize (X: in out Private_Component);
type MasterC is tagged record
P : Private_Component;
end record;
end MasterClass;
package body MasterClass is
numObjects : Integer := 0;
type Private_Part is record -- complete declaration
fTest1, fTest2 : float := 0.0;
end record;
overriding procedure Initialize (X: in out Private_Component) is
begin
X.P := new Private_Part'(fTest1=>0.0, fTest2 => 0.0);
end Initialize;
overriding procedure Adjust (X: in out Private_Component) is
begin
X.P := new Private_Part'(fTest1 => X.P.fTest1, fTest2 => X.P.fTest2);
end Adjust;
overriding procedure Finalize (X: in out Private_Component) is
procedure Free is new Ada.Unchecked_Deallocation (Private_Part, Private_Part_Pointer);
begin
Free (X.P);
end Finalize;
function Make (f1, f2 : Float ) return MasterC is
begin
numObjects := numObjects + 1;
return new MasterC'(fTest1=>0.0, fTest2=>0.0); -- This is not working!
end Make;
procedure do( This : in MasterC ) is
begin
Put_Line( "doneMaster");
end do;
function getVar( This : MasterC )
return float is
begin
return This.P.P.fTest1; -- This is not working!
end getVar;
end MasterClass;
with MasterClass; use MasterClass;
package SubClass is
type SubC is new MasterClass.MasterC with
record
fExtra1 : float := 0.0;
fExtra2 : float := 0.0;
end record;
type SubC_Class_Ref is access all SubC'Class;
overriding procedure do(This : SubC);
function Make (f1, f2 : Float) return SubC;
function Make1 (f1, f2 , w, h: Float) return SubC;
end SubClass;
with MasterClass; use MasterClass;
package body SubClass is
function Make ( f1, f2 : Float ) return SubC is
begin
return ((fTest1 => f1, fTest2 => f2, fExtra1 => 0.0, fExtra2 => 0.0));
end Make;
function Make1 ( f1, f2, w, h: Float ) return SubC is
begin
return (fTest1 => f1, fTest2 => f2, fExtra1 => w, fExtra2 => h);
end Make1;
overriding procedure do( This : in SubC ) is
begin
do(MasterC(This));
Put_Line( "doneSub");
end do;
end SubClass;
我找不到任何信息如何实现这一点
我不知道如何实现的行是Make函数中的返回行
return new MasterC'(fTest1=>0.0, fTest2=>0.0); -- This is not working!
然后是用于读取值的行
return This.P.P.fTest1; -- This is not working!
然后是子类的Make函数中的行
return ((fTest1 => f1, fTest2 => f2, fExtra1 => 0.0, fExtra2 => 0.0)); -- This is not working!
与Java不同,创建对象不需要
new
new
专门分配一个对象并返回对该对象的访问权。因此:
return new MasterC'(fTest1=>0.0, fTest2=>0.0); -- This is not working!
由于函数声明为返回MasterC
,而不是access MasterC
或声明为access MasterC
的任何类型(或access all MasterC'class
或任何类似类型),因此失败。该函数根本不返回访问类型。所以不要使用new
。相反,该表格将
return (P => ???); -- keep reading to see what ??? is
p的值
这里是一个私有组件
。这是Ada.Finalization.Controlled的子类型,带有一个附加组件P
,因此语法如下
return (P => (Ada.Finalization.Controlled with P => ???))
p
的值将是Private\u Part\u指针
,它是一种访问类型(到Private\u Part
),因此您将在这里使用new
return (P => (Ada.Finalization.Controlled with P =>
new Private_Part' (ftest1=>0.0, ftest2=>0.0)));
其实没那么复杂。要创建记录类型的值,请将值放在括号中,括号中的组件名称=>
后跟每个组件的值。要创建访问类型的值,请使用new
当返回SubC
时,事情会变得有趣。SubC
具有与MasterC
相同的组件,以及您添加的两个组件。因此,它有三个组件:P
,fExtra1
,fExtra2
。但是,在这里不能使用名称P
,因为它位于MasterClass
的私有部分,因此子类不可见。要创建SubC
,必须调用函数来创建SubC
的MasterC
部分。结果将类似于
return (MasterClass.Make(f1, f2) with fExtra1 => 0.0, fExtra2 => 0.0);
[注意:这称为扩展聚合
]
这将使用MasterClass.Make
创建一个MasterC
,它将有一个p
组件;SubC
函数结果将P
组件与指定的fExtra1
和fExtra2
一起使用,以创建SubC
所需的三个组件
免责声明:我还没有测试过这个(我在家,手边没有编译器),所以我可能有一些语法错误,或者可能有其他我遗漏的细微错误
编辑:现在我可以使用编译器了,我发现上面的两个更改使您的源代码可以编译(第二个更改必须在两个地方实现);除了do
是一个保留字,不能用作过程名称,而且printNumObjects
需要一个主体。本声明:
return This.P.P.fTest1; -- This is not working!
用我的编译器编译得很好。ajb的答案是非常好的,但我希望您允许我“使用”Ada的OOP工具,因为它们实际上与Java等价物有很大的不同我在这里输入的是我的想法,因此示例可能不可编译,但应该这样做才能让大家理解我的想法
Package Test_1 is
Type Point is record
x, y : Integer;
end record;
-- Some operations
End Test_1;
在上面我们创建了一个类型,但这里有一个问题:它暴露了实现,用户可以直接去更改值,如果需要确保某些进程/属性,这可能是灾难性的。(它还引入了对实施细节的依赖性。)
为了解决这个问题,我们可以将记录私有化,并让客户端使用函数和过程来更改内部状态——就像getter和setter一样(但我们还没有涉及任何OOP)
在上面的示例中,更改是为了使实现是私有的,这允许我们更改实现(请参见下文),而无需强制客户端重新编译。(我们可以将Test_3
更改为Test_2
,它仍然可以工作。)
因此,正如您所看到的,private
在Ada中的含义与在Java中的含义不同。由于Ada在添加OOP(在Ada 95中)之前就有了private
的概念,因此它被带入了OOP。(基本上,其思想是私有类型实现中的更改不会导致程序更改状态,从而成为合法或非法。)
如您所见,Ada还具有记录和间接访问[私有类型]甚至继承[派生类型]的概念。。。但是Ada仍然有类型的概念,特别是可以禁止交互的不同类型(一种类型表示长度,另一种类型表示重量),并且子类型(具有附加约束的类型)差异很大,不适合,因此它们需要某种方法来区分类型和类型“类型或从中派生的东西”是'class
属性的来源:类型\名称'class
表示标记类型的继承树的整个分支
-- Declare an operation that must be overridden in derived types,
-- and which takes the specific type:
Function Operation( Input : Type_Name ) return Boolean is abstract;
-- Declare an operation that takes the whole class:
Function Operation( Input : Type_Name'Class ) return Boolean;
由于上面的规则,具有一些私有组件的记录需要位于规范的私有部分,以便对其内部结构的更改不会影响规范的合法性
Package Test_3 is
Type Point is private;
Function Create( x, y : Integer ) return Point;
Function Get_X ( P : Point ) return Integer;
Function Get_Y ( P : Point ) return Integer;
-- Some more operations.
Private
Type Point is record
x, y : Float;
end record;
-- Ada 2012 expression-functions, for brevity.
Function Create( x, y : Integer ) return Point is
( x => Float(x), y => Float(y) );
Function Get_X ( P : Point ) return Integer is
( Integer(P.X) );
Function Get_Y ( P : Point ) return Integer is
( Integer(P.Y) );
End Test_3;
-- Declare an operation that must be overridden in derived types,
-- and which takes the specific type:
Function Operation( Input : Type_Name ) return Boolean is abstract;
-- Declare an operation that takes the whole class:
Function Operation( Input : Type_Name'Class ) return Boolean;