Four versions of Ada, named after the year it was released: 83, 95, 2005, and 2012. Each new version adds features on top of the previous.
Ada 83 has
- arrays,
- records (structs),
- derived types (subtypes carrying the same data as parent type),
- subtypes,
- access types (thick pointers),
- procedures (subprograms executed for their side effects) and functions (subprograms that return values),
- Named parameters
- reference arguments (greatly reducing the amount of pointers you have to deal with)
- Default values for arguments
- overloading by type
- in/out parameters
- private package parts (encapsulation)
- generic packages (kinda like C++ templates)
- exceptions
- tasks (concurrent processes that communicate with message passing)
-----
Ada 95 adds a lot of things that make it easier to do Java-style OOP:
- Record extension (inheritance; subtypes carrying additional data their parent type does not)
- Dynamic dispatch of subtypes
- Abstract types
- Subprogram access types (function pointers)
- Sophisticated package hierarchy (though potentially somewhat unintuitive: child packages extend their parents, parent packages are not umbrellas for children the way they are in Python)
- Protected types (protected objects)
- Modular types (unsigned ints with defined overflow characteristics)
- Unbounded_String (the std::string of Ada, compared to the char[] situation in Ada 83)
-----
In Ada 2005, the greatest addition is probably the Collections packages, which added several common data structures to the standard library:
- Instance.Method(Param) syntax sugar for Object.Method(Instance, Param)
- Interfaces
- Controlled types (RAII)
- Removed silly restrictions on access types
- Keyword "limited" to import only declarations
- Keyword "raise" takes exception message directly
- Pragma Assert
...and this is where I need to get off the train. Anyway, bookmark the Ada 2012 Reference Manual. It has everything in it.
Edit: ...but look what I found! https://www.adacore.com/about-ada/comparison-chart