In general, I find the heavy use of pragmas unpleasant.

As was pointed out by someone else, Ada supports object-oriented
programming, but it does not do so in exactly the same way
as C++ or Eiffel.  It has more in common with Common Lisp Object System
and Haskell, where there can be multiple "controlling" operands, and they are
all "inside" the parentheses.  This has a number of advantages.
In particular, it makes binary operations much more natural,
and it makes specifying the parameter mode of the controlling operand(s)
straightforward (compare this with the bizarre placement of "const" in C++
for the "this" parameter).

The key to all modern programming languages is the idea of
abstraction.  An abstraction is defined by zero or
more types and a set of operations.

With object-oriented programming, one can create
hierarchies of abstractions, either at the interface level
or at the implementation level.  Furthermore, individual
objects carry around at run-time an indication of their implementation
(which is called the "tag" in Ada), while at compile-time what matters
is the interfaces compatible with the object.

My bottom line would be to focus more on the abstractions, and
less on a rigid set of idioms for implementing them.

-Tuck