Before we begin, mandatory dictionary definition:
ab·stract [adj] /abˈstrakt,ˈabˌstrakt/
- existing in thought or as an idea but not having a physical or concrete existence.
Abstractions are an extremely helpful, albeit difficult to understand concept in programming. After all, if abstractions were easy to understand they probably wouldn't be abstract... Would they?
Abstract classes are just one form of abstraction that exists in programming, and the one I'll be going over in this post. This was inspired by a question from@girng on thecrystal-lang forum. Since the original question was a Crystal question, and since Crystal is currently my favorite language I will be using Crystal examples, but a lot of the concepts transfer to other languages, even if the implementation is different.
What are abstract classes?
Abstract classes are classes which are meant to be inherited, but not instantiated. They act as a base for other classes by providing methods that are should exist on all child classes without actually implementing those methods.
An example of a simple abstract class is as follows:
abstractclassFooabstractdefbar(text:String):Array(String)end
In this case we have a classFoo
which has an abstract methodbar
. Thebar
method must accept a single string parameter and must return a string array. Note that if we try and create an instance of theFoo
class the compiler will throw an error. If we wantFoo
to be useful we have to extend it.
classBaz<Foodefbar(text:String)text.split(" ")endend
Now we've defined a classBaz
which implements thebar
method exactly as described. Let's try and make the compiler throw an error though.
# This will throw an error since `bar` is not defined on `Baz`classBaz<Fooend# This will throw an error since `bar` has the incorrect definitionclassBaz<Foodefbar(opts:Array(String))opts.joinendend
Abstract classes can also define actual methods to be included in child classes. Those methods can be initializers or any other type of method.
classFoodefinitializeputs"#{self.class} initalized"endabstractdefbar(text:String):Array(String)endclassBaz<Foodefbar(text:String)text.split(" ")endendbaz=Baz.new# => "Baz initalized"
Where should I use them?
Abstract classes are useful in a number of situations, but the number one example that springs to mind is with adapters, such as for different databases. Databases are a good example because they all have similar functionality, but they all do things in a slightly different way.
Here is a super basic example:
classConnection# ImplementationendabstractclassAdapterdefinitialize(@name:String,@url:String)endabstractdefinsert(table,fields):Int64# Other methods...endclassMysql<Adapterdefinsert(table,fields)# Insert stuff0endendclassPostgres<Adapterdefinsert(table,fields)# Insert stuff0endend
Obviously this is not a functional example, but it should compile and illustrates the basic concept. For a working example you can check outGranite::Adapter::Base
fromamberframework/granite.
Thanks for reading this. Please don’t forget to hit one of the the Ego Booster buttons (personally I like the unicorn), and if you feel so inclined share this to social media. If you share to twitter be sure to tag me at @_watzon.
Some helpful links:
https://crystal-lang.org/
https://github.com/kostya/benchmarks
https://github.com/kostya/crystal-benchmarks-game
https://github.com/crystal-lang/crystal
Find me online:
https://medium.com/@watzon
https://twitter.com/_watzon
https://github.com/watzon
https://watzon.tech
Top comments(1)

- LocationTexas
- WorkOwner, Financing Company at Texas
- Joined
Do you have another example different than "Foo" "Bar"?
I'm a total newbie, and would like to have a more relatable example.
Much appreciated.
For further actions, you may consider blocking this person and/orreporting abuse