覆盖和类型扩展

时间:2013-07-09 20:40:41

标签: oop ada

希望有人可以解释为什么我的程序默认为Piece Type的Move_Piece过程,而不是当我试图移动池塘时Pond类型的Move_Piece过程。当我将Pond类型的变量传递给Move_Piece过程时,“使用基本Move_Piece”被打印而不是“1”。这是为什么?

我正在使用Ada 2005,以防重写关键字显而易见。我希望我没有提供太少的信息。谢谢!

chess_types.ads:

package Chess_Types is
  type Color is (Black, White);
  type Piece is tagged
    record
     Name : String (1 .. 3) := "   ";
     Alive : Boolean := False;
     Team  : Color;
     Coordinate : Integer;
  end record;
  procedure Move_Piece(P: in out Piece);
  -- Board Types
  type Board_Row is array (Positive range 1 .. 8) of Piece;
  type Board_Type is array (Positive range 1 .. 8) of Board_Row;
end Chess_Types;

chess_types.adb:

with Ada.Text_IO;
use Ada.Text_IO;

package body Chess_Types is
   procedure Move_Piece(P: in out Piece) is
   begin
      Put_Line("Using basic Move_Piece");
   end Move_Piece;
end Chess_types;

chess_types-piece_types.ads:

package Chess_Types.Piece_Types is

   type Pond is new Piece with
      record
         First_Move : Boolean := True;
      end record;
   overriding
   procedure Move_Piece(Po: in out Pond);

   type Rook is new Piece with null record;
      overriding
   procedure Move_Piece(Ro: in out Rook);

   type Knight is new Piece with null record;
      overriding
   procedure Move_Piece(Kn: in out Knight);

   type Bishop is new Piece with null record;
      overriding
   procedure Move_Piece(Bi: in out Bishop);

   type Queen is new Piece with null record;
      overriding
   procedure Move_Piece(Qu: in out Queen);

   type King is new Piece with null record;
      overriding
   procedure Move_Piece(Ki: in out King);
end Chess_Types.Piece_Types;

chess_types-piece_types.adb:

with Ada.Text_IO;
use Ada.Text_IO;

package body Chess_Types.Piece_Types is
--   Possible_Moves : array (Integer range 1 .. 100) of Integer range 11 .. 88;
   procedure Move_Piece(Po: in out Pond) is
   begin
      Put_Line("1");
   end Move_Piece;

   procedure Move_Piece(Ro: in out Rook) is
   begin
      Put_Line("2");
   end Move_Piece;

   procedure Move_Piece(Kn: in out Knight) is
   begin
      Put_Line("3");
   end Move_Piece;

   procedure Move_Piece(Bi: in out Bishop) is
   begin
      Put_Line("4");
   end Move_Piece;

   procedure Move_Piece(Qu: in out Queen) is
   begin
      Put_Line("5");
   end Move_Piece;

   procedure Move_Piece(Ki: in out King) is
   begin
      Put_Line("6");
   end Move_Piece;
end Chess_types.Piece_Types;

chess.adb:

with Ada.Text_IO;
with Print_Things;
with Adjust_Board;
with Chess_Types;
with Chess_Types.Piece_Types;
use Ada.Text_IO;
use Print_Things;
use Adjust_Board;
use Chess_Types;
use Chess_Types.Piece_Types;

procedure Chess is
   Board : Board_Type;
   Move  : String (1 .. 5);
   Move_From : Integer range 11 .. 88;
   Move_To   : Integer range 11 .. 88;
begin

   -- Initialize and Print default board
   Initialize_Board(Board);
   Print_Board(Board);

   -- Get the move
   Put_Line("Select a move:");
   Move := Get_Line;
   while move /= "Q" loop
      Move_From := Integer'Value(Move(Move'First .. Move'First + 1));
      Move_To := Integer'Value(Move(Move'First + 3 .. Move'Last));
      --   Put_Line(Integer'Image(Move_From) & " to" & Integer'Image(Move_To));

      -- Associate the move with a piece
      for I in Board'Range(1) loop
         for J in Board'Range(1) loop
            if Move_From = Board(I)(J).Coordinate then
               Move_Piece(Board(I)(J));
            end if;
         end loop;
      end loop;
      -- Print the Board
      Print_Board(Board);
      -- Get the move
      Put_Line("Select a move:");
      Move := Get_Line;
   end loop;


end Chess;

adjust_board.adb:

with Chess_Types;
use Chess_Types;
with Chess_Types.Piece_Types;
use Chess_Types.Piece_Types;
package body Adjust_Board is

   procedure Initialize_Board(Board: in out Board_Type) is
      -- Define White Chess Pieces
      WP1   : Pond := ("wP ", True, White, 12, True);
      WP2   : Pond := ("wP ", True, White, 22, True);
      WP3   : Pond := ("wP ", True, White, 32, True);
      WP4   : Pond := ("wP ", True, White, 42, True);
      WP5   : Pond := ("wP ", True, White, 52, True);
      WP6   : Pond := ("wP ", True, White, 62, True);
      WP7   : Pond := ("wP ", True, White, 72, True);
      WP8   : Pond := ("wP ", True, White, 82, True);
      WR1   : Rook := ("wRk", True, White, 11);
      WR2   : Rook := ("wRk", True, White, 81);
      WK1   : Knight := ("wKn", True, White, 21);
      WK2   : Knight := ("wKn", True, White, 71);
      WB1   : Bishop := ("wBi", True, White, 31);
      WB2   : Bishop := ("wBi", True, White, 61);
      WQ    : Queen := ("wQu", True, White, 41);
      WK    : King := ("wKi", True, White, 51);

      -- Define Black Chess Pieces
      BP1   : Pond := ("bP ", True, Black, 17, True);
      BP2   : Pond := ("bP ", True, Black, 27, True);
      BP3   : Pond := ("bP ", True, Black, 37, True);
      BP4   : Pond := ("bP ", True, Black, 47, True);
      BP5   : Pond := ("bP ", True, Black, 57, True);
      BP6   : Pond := ("bP ", True, Black, 67, True);
      BP7   : Pond := ("bP ", True, Black, 77, True);
      BP8   : Pond := ("bP ", True, Black, 87, True);
      BR1   : Rook := ("bRk", True, Black, 18);
      BR2   : Rook := ("bRk", True, Black, 88);
      BK1   : Knight := ("bKn", True, Black, 28);
      BK2   : Knight := ("bKn", True, Black, 78);
      BB1   : Bishop := ("bBi", True, Black, 38);
      BB2   : Bishop := ("bBi", True, Black, 68);
      BQ    : Queen := ("bQu", True, Black, 48);
      BK    : King := ("bKi", True, Black, 58);

   begin
      -- Initialize Chess Board
      Board(1)(1) := Piece(WR1);
      Board(8)(1) := Piece(WR2);
      Board(2)(1) := Piece(WK1);
      Board(7)(1) := Piece(WK1);
      Board(3)(1) := Piece(WB1);
      Board(6)(1) := Piece(WB1);
      Board(4)(1) := Piece(WQ);
      Board(5)(1) := Piece(WK);
      Board(1)(2) := Piece(WP1);
      Board(2)(2) := Piece(WP2);
      Board(3)(2) := Piece(WP3);
      Board(4)(2) := Piece(WP4);
      Board(5)(2) := Piece(WP5);
      Board(6)(2) := Piece(WP6);
      Board(7)(2) := Piece(WP7);
      Board(8)(2) := Piece(WP8);

      Board(1)(8) := Piece(BR1);
      Board(8)(8) := Piece(BR2);
      Board(2)(8) := Piece(BK1);
      Board(7)(8) := Piece(BK1);
      Board(3)(8) := Piece(BB1);
      Board(6)(8) := Piece(BB1);
      Board(4)(8) := Piece(BQ);
      Board(5)(8) := Piece(BK);
      Board(1)(7) := Piece(BP1);
      Board(2)(7) := Piece(BP2);
      Board(3)(7) := Piece(BP3);
      Board(4)(7) := Piece(BP4);
      Board(5)(7) := Piece(BP5);
      Board(6)(7) := Piece(BP6);
      Board(7)(7) := Piece(BP7);
      Board(8)(7) := Piece(BP8);
   end Initialize_Board;
end Adjust_Board;

1 个答案:

答案 0 :(得分:3)

在chess_types.ads中,添加

type Piece_Acc is access all Piece'Class;

Board_Row需要是Piece_Acc:

的数组
type Board_Row is array (1..8) of Piece_Acc;

你真的希望你的数组中的元素是Piece'Class,但是这不起作用,因为编译器在那时不能告诉可能从Piece派生什么类型以及它们的内存大小是什么,所以它将无法设置数组。所以它需要是一种访问类型。 (在C#或Java中,无论你是否想要它,所有对象都会自动访问类型[指针]。在Ada你需要告诉它什么时候你需要指针。)然后当你在adjust_board.adb中进行设置时,你说出像

这样的话
Board(1)(1) := new Rook' (WR1);

等等,以便创建访问对象。

[另外,这将导致未初始化的Board中的其他所有内容都被初始化为null。如果你想将它初始化为另一个表示“没有片段”的片段,你需要自己分配给电路板中未使用的空格。]

但是一旦完成所有这些,当你说

Board(I)(J).Move_Piece;  -- same as Board(I)(J).all.Move_Piece;

Move_Piece(Board(I)(J).all);

Board的类型(I)(J).all是一个类范围的类型,所以它会像你想要的那样发送到正确的Move_Piece。

请注意,如果您自己使用“new”分配内容,则还必须负责释放以避免内存泄漏(除非所有内容仅分配一次,然后您并不在意)。最好的方法是控制类型,即从Ada.Finalization.Controlled派生出一块。

更多:避免自己处理访问和分配/解除分配的方法可能是使用Ada.Containers.Indefinite_Vectors而不是数组:

subtype Board_Index is Integer range 1 .. 64;
package Chessboard is new Ada.Containers.Indefinite_Vectors (Board_Index, Piece'Class);

这个包不允许多维类型的索引,所以你需要自己计算一个索引(在1..64或0..63的范围内),或者实例化两次我认为很笨重的Indefinite_Vectors。但这应该消除了进行自己的分配的需要,我认为它也会在容器被销毁时为你解除分配。