Golang interfaces
Tags: go, interfaces, polymorphism, oop
Published: 2022-09-25 10:31:00


What made me interested in Go programming language is the concept behind its interfaces. The object oriented programming is conceived differently in Go, if we compare Go OOP to other OOP languages, we will notice a different approach of how objects behave in this language.

Go is famous for its simple and readable syntax, it is a language that contains only 25 built-in keywords. For example, a famous keyword like the `class` keyword (exists in most languages) doesn't exist in the syntax of Go. Instead, the `struct` is an alternative keyword for the class definition.

Because of this simplicity, concepts like inheritance, polymorphism and abstraction are implemented differently in Go.

Before starting to explain interfaces, an object definition in Go is of type `struct`. so in order to define a Person struct in Go, we describe it in the following block of code :

```Go
type Person struct{
    Name string
    Age int
}
```

the person has 2 attributes (Name and Age attributes).

### What is an interface?

An interface is a set of method signatures that a type can implement. therefore, the interface defines the behaviors of the object (any kind of object).

The definition is as simple as that.

For example, let's say we have an interface called `Speak`, it is defined as the following :

```Go
type Speak interface{
    Arabic()
    French()
    English()
}
```

To make a type implement the `Speak` interface, it (object or variable) must define all of the 3 methods implemented abstractly in the Speak interface : `Arabic()`, `French()` and `English()`.

The _Person_ type implements _Speak_, if itself has the 3 methods definitions :

```Go
func (p Person) Arabic(){ /* code here */ }
func (p Person) French(){ /* code here */ }
func (p Person) English(){ /* code here */ }
```

In other languages, you need to inherit from the interface using the keyword `implements`. But you just need to define the functions.

### The capability of an empty interface

Go programming language has static typing, that means that any variable in a program life cycle has to have only one type (built-in or custom). An integer variable remains as an integer variable, the same thing applies for the other types. 
Unlike Python, a variable can change its type only by reassigning it with a new different value.

Yet, Go can imitate dynamic typing of Python, and can change the variable from one type to another in a single program, and we can thank empty interfaces for that.

let's see this in an example :

```Go
func main(){
    var x int
    x = 5
    x = "change x"
    fmt.Println(x)
}
```

we reassigned the integer value `x` by a variable with a different type (a string "change x"), the program then displayed the following error :

```
./prog.go:10:6: cannot use "change x" (untyped string constant) as int value in assignment
```

However, if we change the type of `x` from `int` to an empty interface `interface{}`, the program will run successfully and the variable will be reassigned again.

```Go
func main() {
	var x interface{}
	x = 5
	fmt.Printf("x=%v of type :%T\n", x, x)
	x = "Fares"
	fmt.Printf("x=%v of type :%T", x, x)
}
```

The type of `x` changed dynamically from integer to string, and we can easily reassign it with any existing type in Go.

```
x=5 of type :int
x=Fares of type :string
```

Now, if we declare an empty interface variable without assigning, what can be the result?

it will be a `nil` value.

### Polymorphism using interfaces

if you want to do polymorphism in other languages, you need to make a parent class and multiple children classes inheriting from the parent.
then you declare an array of the parent class type and instantiate the subclasses and adds them to the array.

In GO, things go differently, we can deal with an interface as a global custom type. we can build polymorphism on the example above and try this code block :

```Go
type Speaker interface{
    Arabic()
    English()
    French()
}
type NativeSpeaker struct{
    Name string
}
type ForeignSpeaker struct{
    Name string
    Nationality string
}
func (NS NativeSpeaker) Arabic(){ /* code here */ }
func (NS NativeSpeaker) English(){ /* code here */ }
func (NS NativeSpeaker) French(){ /* code here */ }
func (FS foreignSpeaker) Arabic(){ /* code here */ }
func (FS ForeignSpeaker) English(){ /* code here */ }
func (FS ForeignSpeaker) French(){ /* code here */ }

func main() {
    listOfSpeakers := make([]Speaker, 0)
    Sp1 := NativeSpeaker{Name: "John"}
    Sp2 := ForeignSpeaker{Name: "Mohamed"}
    listOfSpeakers = append(listOfSpeakers, Sp1, Sp2)
    fmt.Println(listOfSpeakers)
}
```

As you can see the Speaker interface is the global types that assembles `NativeSpeaker` and `ForeignSpeaker` custom types. those shares the same method signatures that were declared in `Speak` interface.