# Polymorphism in Go lang

Polymorphism is the ability of an object or function to take on multiple forms. In the Go programming language, polymorphism is supported through the use of interfaces.

An interface in Go defines a set of methods that a type must implement to satisfy the interface. This means that any type that implements the methods defined in an interface is said to implement the interface.

For example, suppose we have an interface called `Shape` that defines the methods `Area()` and `Perimeter()` for calculating the area and perimeter of a shape. We could define the `Shape` interface like this:

```go
type Shape interface {
    Area() float64
    Perimeter() float64
}
```

Now, any type that implements the `Area()` and `Perimeter()` methods can be said to implement the `Shape` interface. For example, we could define a `Rectangle` type that satisfies the `Shape` interface like this:

```go
type Rectangle struct {
    width  float64
    height float64
}

func (r *Rectangle) Area() float64 {
    return r.width * r.height
}

func (r *Rectangle) Perimeter() float64 {
    return 2 * (r.width + r.height)
}
```

Here, the `Rectangle` type implements the `Area()` and `Perimeter()` methods, so it satisfies the `Shape` interface. This means that we can use a `Rectangle` value wherever a `Shape` is expected, and the appropriate method will be called automatically.

In this way, polymorphism in Go allows us to write code that can work with multiple types in a consistent manner, without needing to know the specific type of an object at compile time.

# Example Code

```go
package main

import "fmt"

type person struct{
    firstname string;
    lastname string
}

type human interface{
   talk()
}

func (p person) talk(){
  fmt.Println("My name is", p.firstname)
}
func main(){
    person1 := person{
        firstname: "Alfred",
        lastname: "Johnson-awah",
    }
    
    person1.talk()
}
```

In the code above we created a person `struct` which has the `firstname` and `lastname`properties. To showcase polymorphism, we created an interface with a function of talk. Lastly, we have implemented the talk function and attached it to a struct type of `person` . This means that any identifier of type `person` would always have a method `talk` and at the end of the day, we can boldly say that the identifier (`person1` in our case) is of both `person` and `human` type, this is polymorphism.

You can still go ahead and add more complex code by implementing type assertion using a `switch` statement as seen below.

```go
package main

import "fmt"

type person struct {
	firstname string
	lastname  string
}

type seniorMan struct {
	person
	hasACar bool
}

type human interface {
	talk()
}

func (p person) talk() {
	fmt.Println("My name is", p.firstname)
}

func (p seniorMan) talk() {
	fmt.Println("I am a person and senior man, see my ID", p, "and i have a car too", p.hasACar)
}

func resolveType(h human) {
	switch t := h.(type) {
	case person:
		fmt.Println("This is a normal person", t.firstname)
	case seniorMan:
		fmt.Println("This is a senior man, does this person have a car?", t.hasACar)

	}
}
func main() {
	person1 := person{
		firstname: "Alfred",
		lastname:  "Johnson-awah",
	}

	seniorMan1 := seniorMan{
		person: person{
			firstname: "Joe",
			lastname:  "Biden",
		},
		hasACar: true,
	}

	resolveType(seniorMan1)
    resolveType(person1)

	person1.talk()
}
```

Running this code on the console, your output should be like the below:

```markdown
This is a senior man, does this person have a car? true
This is a normal person Alfred
My name is Alfred
```

The `seniorMan` struct type inherits properties of the `person` struct type with an additional property `hasACar` . The most important exerpt of this code is the `resolveType` function which uses a switch state to person type assertion on interfaces to find out their underlying types and execute the correct block of code.

## Conclusion

In this blog post, we learnt about polymorphism and how it stems from interface implementation.
