在Ada中使用私有类型创建私有int 我试图在艾达中实现一个私有类型,就像它在java或C++中使用一样。例如,我想在Ada中有一个“private int”

在Ada中使用私有类型创建私有int 我试图在艾达中实现一个私有类型,就像它在java或C++中使用一样。例如,我想在Ada中有一个“private int”,ada,Ada,正如我在这里发现的,我必须在包体中实现我的变量。所以我试着实现这个,就像示例中描述的那样 我的问题是,我无法创建用于创建对象的create函数并设置值。我的第二个问题是,我想要这样的孩子。这些子类应该有一个Create函数,用于设置主类和子类的值 这是我不工作的代码。我补充了一些不起作用的观点 private with Ada.Finalization; package MasterClass is type MasterC is tagged private; type

正如我在这里发现的,我必须在包体中实现我的变量。所以我试着实现这个,就像示例中描述的那样

我的问题是,我无法创建用于创建对象的create函数并设置值。我的第二个问题是,我想要这样的孩子。这些子类应该有一个Create函数,用于设置主类和子类的值

这是我不工作的代码。我补充了一些不起作用的观点

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;