Ada中的构造函数 我试图实现一个构造函数,它在艾达2005中使用java或C++。

Ada中的构造函数 我试图实现一个构造函数,它在艾达2005中使用java或C++。,java,ada,Java,Ada,我有一个Java类: public class MyClass { private static int intTest = 0; private float floatTest = 0.0f; private float floatTest2 = 0.0f; public MyClass(float f_test, float f_test1) { MyClass.intTest++; this.floatTest = f

我有一个Java类:

public class MyClass {
    private static int intTest = 0; 
    private float floatTest = 0.0f; 
    private float floatTest2 = 0.0f; 

    public MyClass(float f_test, float f_test1) {
        MyClass.intTest++;
        this.floatTest = f_test;
        this.floatTest2 = f_test1;       
    }
}
现在我正试图在ADA2005中实现这一点。这是我做的,但我犯了一个错误

with Ada.Finalization; use Ada.Finalization;
package MyClasses is    
    type MyClass (f_test, f_test1 : float)
        is new Controlled with private; 
    type MyClass is access all MyClass'Class;   
    private
        intTest : Integer := 0;
        type MyClass( f_test, f_test1: float )
            is new Controlled with
            record
                floatTest : float := f_test;
                floatTest2 : float := f_test1;
            end record;
overriding procedure Initialize (This : in out MyClass);    
end MyClass;

with Ada.Text_IO; 
use Ada.Text_IO;
package body MyClasses is
    procedure Initialize( This : in out MyClass ) is
    begin       
        intTest := intTest + 1;     
    end Initialize;
end MyClass;
在这一行,我得到了错误“鉴别器必须具有离散或访问类型”


如何像在java类中一样实现构造函数?

Float不是离散类型,并且“鉴别器必须具有离散或访问类型”。艾达没有C++语言启发的语言类中的构造函数。试图改变歧视的用途就像试图在墙上钉一颗螺丝钉。如果它真的起作用的话,结果也不会很好

相反,您应该有一个creator函数来返回初始化的对象:

type MyClass is new Controlled with private;
function Create(f_test, f_test1 : float) return MyClass;
其他需要注意的事项:

  • 您的访问类型MyClass与记录类型具有相同的名称。那不行
  • 在Java示例中,您将intTest声明为
    private static
    ,但在Ada包的private部分中声明了它。这相当于受保护的,因为子包可以访问它。相反,在包体中声明它,这是真正等价于
    私有静态

下面是一个Ada包,它实现了一个带有与Java类类似属性的标记类型:

package My_Class is
   type Instance is tagged private;

   function Create (F_Test, F_Test_1 : Float) return Instance;
private
   type Instance is tagged
      record
         Float_Test, Float_Test_2 : Float := 0.0;
      end record;
end My_Class;

package body My_Class is
   Constructed_Objects : Natural := 0;

   function Create (F_Test, F_Test_1 : Float) return Instance is
   begin
      Constructed_Objects := Constructed_Objects + 1;
      return (Float_Test   => F_Test,
              Float_Test_2 => F_Test_1);
   end Create;
end My_Class;
我忽略了控制标记类型,因为我看不出这样做的意义


Ada不允许将公开可访问类型的完整声明推迟到包规范的私有部分。包规范的私有部分对包的子级可见(与派生类/标记类型不同),这意味着Ada中的“私有”属性在某种程度上类似于Java中的“受保护”属性。

您可以使用通用包作为伪对象的形式,也可以使用Ada控制的记录。泛型包的优点是能够像模板一样将类型作为约束(数组、类型、非歧视),但是ada控制的记录更简单,更易于使用,但仅限于离散类型作为参数(这就是您所做的)。我在为Doom3创建任务安全控制台变量时使用了类似的策略

下面是一个通用包的示例,它是一个带有构造函数和解构器的对象

with Ada.Finalization; use Ada.Finalization;
with Ada.Text_IO; use Ada.Text_IO;
generic
  F_Test_1 : Float;
  F_Test_2 : Float := 2.0;
package Pretend_Class is
  procedure Set_Total(Amount : Integer);
  function Get_Total return Integer;
private
  Total : Integer := 0; -- Total : Integer := Integer(F_Test_1 + F_Test_2) + 1;
                        -- Could just do this and ignore the executable section
                        -- and the controller object, but you may run into an
                        -- elaboration check failure if a function is called 
                        -- in the assignment that was a member function of
                        -- the Pretend_Class package (e.g.
-- Total : Integer := Integer(F_Test_1 + F_Test_2) + 1 + Get_Total; -- Error!
  type Record_Controller is new Ada.Finalization.Controlled with null record;
  overriding procedure Initialize (Controller : in out Record_Controller);
  overriding procedure Finalize   (Controller : in out Record_Controller);
  Controller : Record_Controller;
end Pretend_Class;

package body Pretend_Class is
  procedure Set_Total(Amount : Integer) is
    begin
      Put_Line(" Total is now" Integer'image(Total));   
      Total := Amount;
    end Set_Total;
  function Get_Total return Integer is
    begin
      return Total;
    end Get_Total;
  procedure Initialize(Controller : in out Record_Controller) is
    begin       
      Total := Integer(F_Test_1 + F_Test_2);
      Total := Total + 1;     
    end Initialize;
  procedure Finalize(Controller : in out Record_Controller) is
    begin       
      Total := 0;     
    end Finalize;
begin
  null; -- Total := Integer(F_Test_1 + F_Test_2) + 1 + Get_Total; -- Works here!
        -- You can also just initialize in the executable section
        -- and remove the controller object but you lose the ability
        -- to finalize
end Pretend_Class;

with Pretend_Class;
procedure Test is
  package My_Pretend_Class is new Pretend_Class(F_Test_1 => 3.0);
  begin
    My_Pretend_Class.Set_Total(Amount => 2);
  end Test;

从一个角度来看,对象工厂模式是创建对象的自然Ada-2005方法。我知道每个返回标记类型的函数都可以是构造函数。但是为了创建一个对象,我必须执行create函数。正如这里提到的,我希望有一个自动构造函数,这样我就可以创建一个P:=newmyclass(20.0,10.0)的对象。这个参数不可能吗?@user1058712:您可以执行
P:=newmyclass'(创建(20.0,10.0)),你的私有属性是对的。但是我认为Float_测试和Float_测试_2也应该在包体中吗?这取决于您的需求。Ada不仅仅是具有不同语法的Java。这是一种不同的语言。仅仅因为你通常用一种语言以特定的方式做一些事情,所以用另一种语言100%地匹配它通常不是一个好主意。
with Ada.Finalization; use Ada.Finalization;
with Ada.Text_IO; use Ada.Text_IO;
generic
  F_Test_1 : Float;
  F_Test_2 : Float := 2.0;
package Pretend_Class is
  procedure Set_Total(Amount : Integer);
  function Get_Total return Integer;
private
  Total : Integer := 0; -- Total : Integer := Integer(F_Test_1 + F_Test_2) + 1;
                        -- Could just do this and ignore the executable section
                        -- and the controller object, but you may run into an
                        -- elaboration check failure if a function is called 
                        -- in the assignment that was a member function of
                        -- the Pretend_Class package (e.g.
-- Total : Integer := Integer(F_Test_1 + F_Test_2) + 1 + Get_Total; -- Error!
  type Record_Controller is new Ada.Finalization.Controlled with null record;
  overriding procedure Initialize (Controller : in out Record_Controller);
  overriding procedure Finalize   (Controller : in out Record_Controller);
  Controller : Record_Controller;
end Pretend_Class;

package body Pretend_Class is
  procedure Set_Total(Amount : Integer) is
    begin
      Put_Line(" Total is now" Integer'image(Total));   
      Total := Amount;
    end Set_Total;
  function Get_Total return Integer is
    begin
      return Total;
    end Get_Total;
  procedure Initialize(Controller : in out Record_Controller) is
    begin       
      Total := Integer(F_Test_1 + F_Test_2);
      Total := Total + 1;     
    end Initialize;
  procedure Finalize(Controller : in out Record_Controller) is
    begin       
      Total := 0;     
    end Finalize;
begin
  null; -- Total := Integer(F_Test_1 + F_Test_2) + 1 + Get_Total; -- Works here!
        -- You can also just initialize in the executable section
        -- and remove the controller object but you lose the ability
        -- to finalize
end Pretend_Class;

with Pretend_Class;
procedure Test is
  package My_Pretend_Class is new Pretend_Class(F_Test_1 => 3.0);
  begin
    My_Pretend_Class.Set_Total(Amount => 2);
  end Test;