# Interfaces and Polymorphism

Course: [Go](https://www.devtutorials.ai/learn/go) · Section: Types and OOP
Source: https://www.devtutorials.ai/learn/go/types-and-oop/interfaces-and-polymorphism

> Go interfaces: implicit implementation, single and multiple-method interfaces, interface values, nil interfaces, any, type assertions, type switches and polymorphism.

## What Are Interfaces?

**Interface** = a list of methods. Any type that has all those methods can be used where the interface is asked for.

- An interface says **what** something can do.
- It does not say **how** it does it.
- Many different types can fit one interface.

**Simple lesson:** an interface is a list of abilities, and any type with those abilities fits.

### A Real-World Example

Think of the school's charging point.

- The socket does not care **what** you plug in.
- A phone, a tablet or a torch: if it has the right **plug**, it works.
- The socket only asks for one ability: "fits this plug".

Now the mapping:

- **The socket** = a function that takes an interface.
- **The plug shape** = the interface's method list.
- **Phone, tablet, torch** = different types that have that method.

In Go, a type fits an interface **automatically**, just by having the methods.

There is no `implements` keyword. This is called **implicit implementation**.

## What You Will Learn

In this lesson, you will learn:

1. What interfaces are, why they are used, and how implicit implementation works.
2. How to define single-method and multiple-method interfaces.
3. What an interface value holds: a dynamic type and a dynamic value.
4. The empty interface, `any`.
5. Type assertions and type switches.
6. Polymorphism: one piece of code working with many types.

## Interface Fundamentals

### Why Interfaces Are Used

- **Write one function** that works with many types.
- **Swap parts easily:** a real database or a fake one for testing.
- **Hide details:** the caller only sees the methods it needs.
- **Connect packages** without them knowing each other's types.

### Implicit Implementation

**Implement** = have every method an interface lists.

Pick each shape. Does it fit `Shape`?

Look at two things:

- **Rect and Circle** have both methods, so they fit.
- **Square and Line** are each missing a method, so Go refuses them.

```go runnable title="Two types, one interface"
package main

import "fmt"

type Shape interface {
	Area() float64
}

type Rect struct {
	W, H float64
}

func (r Rect) Area() float64 {
	return r.W * r.H
}

type Circle struct {
	R float64
}

func (c Circle) Area() float64 {
	return 3.14 * c.R * c.R
}

func main() {
	var s Shape
	s = Rect{4, 5}
	fmt.Println(s.Area())
	s = Circle{2}
	fmt.Println(s.Area())
}
```

```text
20
12.56
```

- `Rect` and `Circle` never mention `Shape`.
- They both have `Area() float64`, so both fit.
- `s` can hold either one.

**Simple lesson:** a type fits an interface just by having all its methods.

## Creating Interfaces

### Interface Definitions

```go
type Name interface {
	Method1(params) results
	Method2(params) results
}
```

- List only method **signatures**: name, parameters, results.
- No fields, no code.

### Single-Method Interfaces

Go loves small interfaces. Their names often end in **-er**.

| Interface | Method | Means |
|---|---|---|
| `fmt.Stringer` | `String() string` | can describe itself as text |
| `io.Reader` | `Read(p []byte) (int, error)` | can give bytes |
| `io.Writer` | `Write(p []byte) (int, error)` | can take bytes |
| `error` | `Error() string` | can describe a problem |

```go runnable title="fmt.Stringer: control how a value prints"
package main

import "fmt"

type Student struct {
	Name  string
	Class string
}

func (s Student) String() string {
	return s.Name + " of class " + s.Class
}

func main() {
	asha := Student{"Asha", "8A"}
	fmt.Println(asha)
}
```

```text
Asha of class 8A
```

- `Student` has `String() string`, so it fits `fmt.Stringer`.
- `fmt.Println` checks for that interface and uses your method.

### Multiple-Method Interfaces

```go runnable title="An interface with two methods"
package main

import "fmt"

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

type Rect struct {
	W, H float64
}

func (r Rect) Area() float64      { return r.W * r.H }
func (r Rect) Perimeter() float64 { return 2 * (r.W + r.H) }

func describe(s Shape) {
	fmt.Println("Area:", s.Area(), "Perimeter:", s.Perimeter())
}

func main() {
	describe(Rect{3, 4})
}
```

```text
Area: 12 Perimeter: 14
```

- A type must have **every** method to fit.
- Smaller interfaces are easier to fit. Prefer them.

**Simple lesson:** an interface is a list of method signatures, and small ones are best.

## Interface Values

An interface variable holds two things inside:

- **Dynamic type** = the real type it holds right now, like `Rect`.
- **Dynamic value** = the real value, like `{3 4}`.

### Dynamic Values and Dynamic Types

```go runnable title="One variable, changing inside"
package main

import "fmt"

type Speaker interface {
	Speak() string
}

type Dog struct{}
type Cat struct{}

func (Dog) Speak() string { return "Woof" }
func (Cat) Speak() string { return "Meow" }

func main() {
	var s Speaker
	s = Dog{}
	fmt.Println(s.Speak())
	s = Cat{}
	fmt.Println(s.Speak())
}
```

```text
Woof
Meow
```

- The variable `s` has the static type `Speaker`.
- Its dynamic type changes from `Dog` to `Cat`.
- Go calls the method of the dynamic type.

### nil Interfaces

A new interface variable holds **no type and no value**. It is `nil`.

```go runnable title="A nil interface"
package main

import "fmt"

type Speaker interface {
	Speak() string
}

func main() {
	var s Speaker
	fmt.Println(s == nil)
	if s != nil {
		fmt.Println(s.Speak())
	} else {
		fmt.Println("nobody to speak")
	}
}
```

```text
true
nobody to speak
```

- Calling a method on a nil interface panics. Check first.

An interface is only `nil` when **both** its type and value are empty.

```go
var p *MyError = nil
var err error = p
fmt.Println(err == nil) // false in Go!
```

The interface holds the type `*MyError`, so it is not nil, even though the pointer is. Return a plain `nil` when there is no error. See **Error Handling**.

**Simple lesson:** an interface value holds a real type and a real value, and it is nil only when both are empty.

## Empty Interface

### any and `interface{}`

**Empty interface** = `interface{}`, an interface with no methods.

**`any`** = a shorter name for `interface{}`.

- Every type has "no methods required", so **every** value fits `any`.
- `fmt.Println` takes `...any`. That is why it prints anything.

```go runnable title="any holds anything"
package main

import "fmt"

func main() {
	var box any
	box = 42
	fmt.Println(box)
	box = "Green Valley"
	fmt.Println(box)
	items := []any{7, 3.5, "pen", true}
	fmt.Println(items, len(items))
}
```

```text
42
Green Valley
[7 3.5 pen true] 4
```

- `any` gives up type safety: Go no longer knows what is inside.
- To use the value, you must get its real type back. See the next section.
- Prefer real types, or generics, when you can. See **Generics**.

**Simple lesson:** `any` can hold every value, but you must check its type before you use it.

## Type Assertions

### Type Assertion Basics

**Type assertion** = `x.(T)`: take the value of type `T` out of an interface.

```go runnable title="Get the int back"
package main

import "fmt"

func main() {
	var box any = 90
	marks := box.(int)
	fmt.Println(marks + 5)
}
```

```text
95
```

```go runnable expect-error title="A wrong assertion panics"
package main

import "fmt"

func main() {
	var box any = "ninety"
	marks := box.(int)
	fmt.Println(marks)
}
```

- The value is a `string`, not an `int`.
- The program stops: `panic: interface conversion: interface {} is string, not int`.

### Safe Assertions

**Comma-ok assertion** = `v, ok := x.(T)`. No panic: `ok` tells you if it worked.

```go runnable title="Assert safely"
package main

import "fmt"

func main() {
	var box any = "ninety"
	if n, ok := box.(int); ok {
		fmt.Println("number:", n)
	} else {
		fmt.Println("not a number, it is:", box)
	}
}
```

```text
not a number, it is: ninety
```

- This is the same comma-ok idea as with maps. See **Maps**.

**Simple lesson:** `x.(T)` gets the real value out, and `v, ok := x.(T)` does it safely.

## Type Switches

### Dynamic Type Handling

**Type switch** = a `switch` that picks a case by the **type** inside an interface.

```go runnable title="Handle each type differently"
package main

import "fmt"

func describe(v any) string {
	switch x := v.(type) {
	case int:
		return fmt.Sprint("whole number ", x)
	case float64:
		return fmt.Sprint("decimal ", x)
	case string:
		return "text of length " + fmt.Sprint(len(x))
	case nil:
		return "nothing"
	default:
		return "something else"
	}
}

func main() {
	fmt.Println(describe(42))
	fmt.Println(describe(3.5))
	fmt.Println(describe("Asha"))
	fmt.Println(describe(nil))
	fmt.Println(describe(true))
}
```

```text
whole number 42
decimal 3.5
text of length 4
nothing
something else
```

- `v.(type)` works only inside a `switch`.
- In each case, `x` already has that case's type.
- In `case string`, `len(x)` works because `x` is a `string`.

**Simple lesson:** a type switch runs a different case for each type inside an interface.

## Polymorphism

**Polymorphism** = one piece of code works with many types, and each type behaves in its own way.

### Interface-Based Polymorphism

In Go, polymorphism comes from interfaces, not from class families.

- A function or loop works with the **interface**.
- Each type gives its own version of the methods.

### Multiple Implementations

Press **Play** to watch one loop call three different methods.

### Runtime Behavior

- The loop is written **once**.
- Which `Send` runs is decided **while the program runs**, by the dynamic type.
- Add a new type, like `WhatsApp`, with a `Send` method, and the loop works with it unchanged.

```go runnable title="Total area of mixed shapes"
package main

import "fmt"

type Shape interface {
	Area() float64
}

type Rect struct{ W, H float64 }
type Square struct{ Side float64 }

func (r Rect) Area() float64   { return r.W * r.H }
func (s Square) Area() float64 { return s.Side * s.Side }

func totalArea(shapes []Shape) float64 {
	total := 0.0
	for _, s := range shapes {
		total += s.Area()
	}
	return total
}

func main() {
	garden := []Shape{Rect{10, 4}, Square{3}, Rect{2, 2.5}}
	fmt.Println("Garden area:", totalArea(garden))
}
```

```text
Garden area: 54
```

**Easy way to remember**

- An interface = "what can it do?"
- A type fits by having the methods. No `implements`.
- Accept interfaces in functions, return concrete types.

**Simple lesson:** with interfaces, one function works with many types, and each type keeps its own behaviour.

## TL;DR

1. **Interface** = a list of methods: `type Shape interface { Area() float64 }`.
2. **Implicit implementation** = a type fits by having every method. No `implements`.
3. **Small interfaces** = `Stringer`, `Reader`, `Writer`, `error`.
4. **Interface value** = dynamic type + dynamic value. `nil` only when both are empty.
5. **Empty interface** = `any` / `interface{}`. Holds every value.
6. **Type assertion** = `x.(T)`, panics if wrong. **Safe** = `v, ok := x.(T)`.
7. **Type switch** = `switch v := x.(type) { case int: ... }`.
8. **Polymorphism** = one loop or function, many types, each with its own behaviour.

## Common mistakes

| Mistake | Wrong idea | Correct idea | What goes wrong |
|---|---|---|---|
| Writing `implements Shape` | Go needs it | Go matches methods automatically | A syntax error. |
| Missing one method | Close enough is fine | Every method is needed | `does not implement Shape (missing method Perimeter)` |
| Pointer-receiver methods with a value | A value fits | Only `*T` has pointer methods | `method Area has pointer receiver` |
| `x.(int)` without checking | It always works | Wrong types panic | `interface conversion` panic. |
| Using `any` everywhere | It is flexible | It loses type checks | Bugs found only at runtime. |
| Returning a nil pointer as `error` | It equals nil | The interface is not nil | `err != nil` is true by mistake. |
| Huge interfaces | More methods = better | Small ones are easier to fit | Few types can use them. |

## Check Yourself

## Exercises

## What to Remember

- An interface lists methods. Any type with those methods fits, automatically.
- Keep interfaces small: `Stringer`, `Reader`, `error`.
- An interface value holds a type and a value. It is nil only when both are empty.
- `any` holds everything. Get values back with `x.(T)`, `v, ok := x.(T)` or a type switch.
- Polymorphism: one loop, many types, each behaving its own way.

Next: **Encapsulation**. You will learn how to hide a type's data and control how it changes.
