Understating abstract classes
Tags: crystal, abstract, class, programming
Published: 2019-07-27 05:54:49

Before we begin, mandatory dictionary definition:

> **ab·stract** [adj] /abˈstrakt,ˈabˌstrakt/
> 1. 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 the [crystal-lang forum](https://forum.crystal-lang.org/t/difference-between-abstract-def-and-def/998). 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:

```crystal
abstract class Foo
  abstract def bar(text : String) : Array(String)
end
```

In this case we have a class `Foo` which has an abstract method `bar`. The `bar` method must accept a single string parameter and must return a string array. Note that if we try and create an instance of the `Foo` class the compiler will throw an error. If we want `Foo` to be useful we have to extend it.

```crystal
class Baz < Foo
  def bar(text : String)
    text.split(" ")
  end
end
```

Now we've defined a class `Baz` which implements the `bar` method exactly as described. Let's try and make the compiler throw an error though.

```crystal
# This will throw an error since `bar` is not defined on `Baz`
class Baz < Foo
end

# This will throw an error since `bar` has the incorrect definition
class Baz < Foo
  def bar(opts : Array(String))
    opts.join
  end
end
```

Abstract classes can also define actual methods to be included in child classes. Those methods can be initializers or any other type of method.

```crystal
class Foo
  def initialize
    puts "#{self.class} initalized"
  end

  abstract def bar(text : String) : Array(String)
end

class Baz < Foo
  def bar(text : String)
    text.split(" ")
  end
end

baz = 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:

```crystal
class Connection
  # Implementation
end

abstract class Adapter

  def initialize(@name : String, @url : String)
  end

  abstract def insert(table, fields) : Int64

  # Other methods...

end

class Mysql < Adapter
  def insert(table, fields)
    # Insert stuff
    0
  end
end

class Postgres < Adapter
  def insert(table, fields)
    # Insert stuff
    0
  end
end
```

Obviously this is not a functional example, but it should compile and illustrates the basic concept. For a working example you can check out [`Granite::Adapter::Base`](https://github.com/amberframework/granite/blob/master/src/adapter/base.cr) from [amberframework/granite](https://github.com/amberframework/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