Logo Questions Linux Laravel Mysql Ubuntu Git Menu
 

What are "abstractions"?

I've been reading Stroustrup's "The C++ Programming Language" and he mentions "abstractions" a lot:

Many of the most flexible, efficient, and useful abstractions involve the parameterization of types (classes) and algorithms (functions) with other types and algorithms

and

C++ is a language for developing and using elegant and efficient abstractions.

Is this in any way related to abstract classes in C++? Or with using polymorphism, inheritance, or templates?

Could someone give an example please?

like image 422
Oleksiy Avatar asked Aug 09 '13 07:08

Oleksiy


People also ask

What is an example of an abstraction?

Your car is a great example of abstraction. You can start a car by turning the key or pressing the start button. You don't need to know how the engine is getting started, what all components your car has. The car internal implementation and complex logic is completely hidden from the user.

What are abstractions used for?

The main purpose of abstraction is hiding the unnecessary details from the users. Abstraction is selecting data from a larger pool to show only relevant details of the object to the user. It helps in reducing programming complexity and efforts.

What are the types of abstractions?

Abstraction can be of two types, namely, data abstraction and control abstraction.


2 Answers

abstraction (n) - the quality of dealing with ideas rather than events

— source: Oxford English Dictionary

Stroustrup is not referring to abstract classes or other specific ideas in programming. Rather, he is referring to the word abstraction itself.

Abstractions are mental helpers. They help us think in "theory" rather than direct application. Mathematics is the art of abstraction. Programming is the art of applied abstractions.

Abstractions help us form mental models, such as hierarchies, to help us think of things. Polymorphism is possible because of abstractions. Let's take a look at an example.

Example

1st level

I have an Oleksiy Dobrodum. I refer to it as an Oleksiy Dobrodum, I treat it like an Oleksiy Dobrodum, all it will ever be is an Oleksiy Dobrodum. Everything I do to this Oleksiy Dobrodum is specifically for it. We're now on the 1st level of abstraction, or the most specific we'll ever be when working with this Oleksiy Dobrodum.

Recently I acquired a Zach Latta, so now I have both an Oleksiy Dobrodum and a Zach Latta.

More 1st level

I could refer to them both individually, so as an Oleksiy Dobrodum and as a Zach Latta, but that would quickly grow redundant and prove to not be flexible. Instead, we can simply group Oleksiy Dobrodum and Zach Latta together and call them Humans. We have now achieve abstraction level 2. Instead of dealing with each person individually, we can refer to them as Humans. By doing this, we have abstracted away the "implementation", or the specific details of each person and have started focusing on the ideas, therefore we are now thinking in the abstract.

More 2nd level

Of course we can abstract this further, but hopefully you're starting to get the idea behind abstractions. The key takeaway from this is that an abstraction hides the details (or implementation). By hiding the details in our Humans abstraction, we allow ourselves to speak in generalities. We'll talk briefly on how this applies in programming in the next section.

Applying Abstractions

Now that we've touched briefly on what an abstraction is, let's apply it. Polymorphism is possible because of abstractions. Following the model of the previous example, say we have the following two classes:

class OleksiyDobrodum
  name = "Oleksiy Dobrodum"
  smarts = :mega-smart
  mood = :happy
  favorite_candy = :chocolate
end

class ZachLatta
  name = "Zach Latta"
  smarts = :so-so
  mood = :indifferent
  hair_color = :brown
end

If I want to interact with an instance of ZachLatta I must refer to it specifically. The same goes for OleksiyDobrodum instances.

zach = new ZachLatta
print zach.name

oleksiy = new OleksiyDobrodum
print oleksiy.favorite_candy

If I create an abstract class called Human and have both OleksiyDobrodum and ZachLatta inherit from it, then I can abstract away the implementation of both classes and simply refer to both instances of them as Human.

class Human
  name
  smarts
  mood
end

class OleksiyDobrodum < Human
  name = "Oleksiy Dobrodum"
  smarts = :mega-smart
  mood = :happy
  favorite_candy = :chocolate
end

class ZachLatta < Human
  name = "Zach Latta"
  smarts = :so-so
  mood = :indifferent
  hair_color = :brown
end

Our class diagram now looks like the following:

Class diagram for code above

I could ramble on about implementation forever, but let's move on to our key takeaways.

Key Takeaways

  • abstractions are ideas, not specific events
  • to abstract something is to move away from its implementation and think about big ideas
  • abstractions can be used to organize code (and many other things) effectively
  • object-oriented programming is entirely dependent on the abstractions. see the above bullet point.
like image 182
Zach Latta Avatar answered Sep 27 '22 18:09

Zach Latta


In generic programming, abstractions have a precise meaning, and are called "concepts". A concept is defined as follows:

A concept is a set of requirements consisting of valid expressions, associated types, invariants, and complexity guarantees. A type that satisfies the requirements is said to model the concept. A concept can extend the requirements of another concept, which is called refinement.

  • Valid Expressions are C++ expressions which must compile successfully for the objects involved in the expression to be considered models of the concept.
  • Associated Types are types that are related to the modeling type in that they participate in one or more of the valid expressions. Typically associated types can be accessed either through typedefs nested within a class definition for the modeling type, or they are accessed through a traits class.
  • Invariants are run-time characteristics of the objects that must always be true, that is, the functions involving the objects must preserve these characteristics. The invariants often take the form of pre-conditions and post-conditions.
  • Complexity Guarantees are maximum limits on how long the execution of one of the valid expressions will take, or how much of various resources its computation will use. The concepts used in the C++ Standard Library are documented at the SGI STL site.

Implementing a concept into real code can be done is several ways. The classical OOP approach is to write an abstract base class providing the valid expressions and associated types. The concrete derived classes then provide the invariants and the complexity guarantees. For templates, the valid expressions are more implicit and only checked after instantiation. Template implementing concepts are a form of duck typing: if it looks like a duck, quacks like a duck, ....

The C++0x development process devoted a lot of effort to make concepts directly expressible into code, but it was not incorporated into the C++11 Standard. However, a Concepts Lite version is likely going to appear into the next C++14 Standard.

like image 28
TemplateRex Avatar answered Sep 27 '22 19:09

TemplateRex