简体   繁体   English

Ada中的构造函数

[英]Constructor in Ada

I am trying to implement a constructor like it is used in Java or C++ in Ada 2005. 我正在尝试实现一个类似于在Ada 2005中用于Java或C ++的构造函数。

I have this class in Java: 我在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;       
    }
}

And now I am trying to implement this in Ada 2005. This is what I did but I get an error. 现在我试图在Ada 2005中实现这一点。这就是我所做的,但是我收到了一个错误。

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;

On this line I get the error "discriminants must have a discrete or access type". 在这一行,我得到错误“判别必须具有离散或访问类型”。

type MyClass (f_test, f_test1 : float)
    is new Controlled with private;

How can I implement the constructor like it is in the java class? 我如何实现像java类中的构造函数?

Float is not a discrete type and "discriminants must have a discrete or access type". 浮点数不是离散类型,“判别式必须具有离散或访问类型”。 Ada does not have the kind of constructors you find in the C++ inspired family of languages. Ada没有你在C ++启发的语言系列中找到的那种构造函数。 Trying to repurpose discriminants for that is like trying to hammer a screw into the wall. 试图重新利用判别力就像试图将螺钉钉在墙上一样。 If it does happen to work the result still won't be pretty. 如果它确实发生了工作,结果仍然不会很好。

Rather you should have a creator function that returns your initialized object: 相反,你应该有一个返回初始化对象的创建者函数:

type MyClass is new Controlled with private;
function Create(f_test, f_test1 : float) return MyClass;

Other things to note: 其他注意事项:

  • Your access type MyClass has the same name as the record type. 您的访问类型MyClass与记录类型具有相同的名称。 That won't work. 那不行。
  • You declared intTest as private static in the Java example, but declared it in the private part of the Ada package. 您在Java示例中将intTest声明为private static ,但在Ada包的私有部分中声明它。 This is equivalent to protected since child packages can access it. 这相当于protected因为子包可以访问它。 Declare it in the package body instead, this is the true equivalent of private static . 相反,它在包体中声明它,这是private static的真正等价物。

Here is an Ada package which implements a tagged type with similar properties to your Java class: 这是一个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;

I have omitted to make the tagged type controlled, as I can't see the point in doing so. 我已经省略了标记类型的控制,因为我无法看到这样做的重点。

Ada doesn't allow you to postpone the full declaration of a publicly visibile type further than to the private part of the package specification. Ada不允许您推迟公开可见类型的完整声明,而不是包规范的私有部分。 The private part of a package specification is visible to children of the package (not the same as derived classes/tagged types), which mean that the "private" attributes in Ada are somewhat similar to "protected" attributes in Java. 包规范的私有部分对包的子节点是可见的(与派生类/标记类型不同),这意味着Ada中的“private”属性有点类似于Java中的“protected”属性。

You can use a generic package as a form of pseudo object or you can use ada controlled record. 您可以使用通用包作为伪对象的形式,也可以使用ada受控记录。 A generic package has the advantage of being able to take types as constraints much like a template (arrays, types, non discriminate), however an ada controlled record is much more simple and easy to use but is limited to discrete types as parameters (which is what you did). 通用包的优点是能够将类型作为约束而非模板(数组,类型,非区分),但ada控制的记录更简单易用,但仅限于离散类型作为参数(是你做的)。 I used a similar strategy when i created task safe console variables for doom 3. 当我为厄运3创建任务安全控制台变量时,我使用了类似的策略。

Here is an example of a generic package as a object with a constructor and deconstructor 下面是一个通用包作为具有构造函数和解构函数的对象的示例

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;

声明:本站的技术帖子网页,遵循CC BY-SA 4.0协议,如果您需要转载,请注明本站网址或者原文地址。任何问题请咨询:yoyou2525@163.com.

 
粤ICP备18138465号  © 2020-2024 STACKOOM.COM