Polymorphism in Go

Polymorphism is a fundamental concept in object-oriented programming (OOP) that allows objects of different types to be treated as instances of a common superclass or to respond to the same interface. While Go does not support class-based inheritance, it provides mechanisms to achieve polymorphism through interfaces.

In Go, you can define interfaces that specify a set of method signatures. Any type that implements all the methods defined in an interface is said to satisfy or implement that interface. This allows for polymorphic behaviour in Go, where different types can be treated interchangeably based on their shared interface.

Here’s an example that demonstrates polymorphism in Go using interfaces:

package main

import "fmt"

type Animal interface {
    Sound() string
}

type Dog struct{}

func (d Dog) Sound() string {
    return "Woof!"
}

type Cat struct{}

func (c Cat) Sound() string {
    return "Meow!"
}

func MakeSound(a Animal) {
    fmt.Println(a.Sound())
}

func main() {
    d := Dog{}
    c := Cat{}

    MakeSound(d)
    MakeSound(c)
}

In this example, we define an Animal interface that specifies a single method Sound(), which returns a string. The Dog and Cat types implement the Animal interface by defining the Sound() method.

The MakeSound() function takes an Animal parameter and calls the Sound() method on it. This function can accept any type that satisfies the Animal interface, allowing us to pass Dog and Cat instances interchangeably.

In the main() function, we create a Dog instance d and a Cat instance c. We then invoke the MakeSound() function with d and c as arguments. Since both Dog and Cat implement the Animal interface, they can be treated as Animal instances, and their respective Sound() methods are called.

When we run the program, the output will be:

Woof!
Meow!

Through interfaces, Go enables polymorphism by allowing different types to be treated interchangeably based on their shared interface. This promotes loose coupling, flexibility, and code reusability.

Polymorphism using an interface in Go

Polymorphism in Go is achieved through interfaces. Interfaces define a set of method signatures, and any type that implements all the methods specified in an interface is said to satisfy that interface. This allows different types to be treated interchangeably based on their shared interface, enabling polymorphic behavior.

Here’s an example that demonstrates polymorphism using an interface in Go:

package main

import "fmt"

type Shape interface {
    Area() float64
}

type Rectangle struct {
    Width  float64
    Height float64
}

func (r Rectangle) Area() float64 {
    return r.Width * r.Height
}

type Circle struct {
    Radius float64
}

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

func PrintArea(s Shape) {
    fmt.Printf("Area: %.2f\n", s.Area())
}

func main() {
    r := Rectangle{Width: 3, Height: 4}
    c := Circle{Radius: 2.5}

    PrintArea(r)
    PrintArea(c)
}

In this example, we define an Shape interface with a single method Area() that returns a float64 value. The Rectangle and Circle types implement the Shape interface by providing their own implementations of the Area() method.

The PrintArea() function takes an Shape parameter and calls the Area() method on it. It can accept any type that satisfies the Shape interface, allowing us to pass Rectangle and Circle instances interchangeably.

In the main() function, we create a Rectangle instance r and a Circle instance c. We invoke the PrintArea() function with r and c as arguments. Since both Rectangle and Circle implement the Shape interface, they can be treated as Shape instances, and their respective Area() methods are called.

When we run the program, the output will be:

Area: 12.00
Area: 19.63

Through the use of interfaces, Go achieves polymorphism by allowing different types to be treated interchangeably based on their shared interface. This promotes code reusability, modularity, and flexibility, allowing you to write more generic and reusable code.