saral

OOPs concept in Golang

First of all, let’s recap what are OOPs principles.

Object-oriented programming (OOP) is a programming paradigm that focuses on representing real-world objects and their relationships in software. OOP is based on the concept of objects, which are instances of classes, and classes provide a blueprint for creating objects. OOP provides several key concepts or principles, which are:

  • Encapsulation: encapsulation is the practice of hiding the implementation details of an object from other objects. Encapsulation is achieved by defining the state and behavior of an object within a class, and providing methods to access and modify the object’s state. This helps to prevent unwanted modifications to the object’s state and provides a clean interface for working with the object.
  • Abstraction: abstraction is the practice of hiding the complex implementation details of an object and exposing only the relevant information to the user. Abstraction is achieved through the use of abstract classes or interfaces, which define a set of methods that can be used to interact with the object. The details of how the methods are implemented are hidden from the user, making it easier to work with the object.
  • Inheritance: inheritance is the practice of creating a new class that is a modified version of an existing class. The new class, called the child class or subclass, inherits the properties and methods of the parent class or superclass. This allows the child class to reuse code from the parent class and add additional functionality of its own.
  • Polymorphism: polymorphism is the practice of allowing objects of different types to be treated as if they were the same type. This is achieved through the use of interfaces or abstract classes. Polymorphism makes it easier to write reusable code that can work with different types of objects, without needing to know the specific details of each object.

Now, Golang and OOPs concepts

The Go FAQ says:

Is Go an object-oriented language?

Yes and no. Although Go has types and methods and allows an object-oriented style of programming, there is no type hierarchy. The concept of “interface” in Go provides a different approach that we believe is easy to use and in some ways more general. There are also ways to embed types in other types to provide something analogous, but not identical, to subclassing. Moreover, methods in Go are more general than in C++ or Java: they can be defined for any sort of data, even built-in types such as plain, “unboxed” integers. They are not restricted to structs (classes).

Also, the lack of a type hierarchy makes “objects” in Go feel much more lightweight than in languages such as C++ or Java.

I can explain how each of the OOP properties can be achieved in Golang.

1. Encapsulation. In Go, encapsulation can be achieved through the use of structs and methods. By defining private fields within a struct and providing public methods to access and modify those fields, you can encapsulate the data and behavior of an object.

For example, consider the following struct:

type Person struct {
	name string
	age  int
}

The name and age fields are private because they start with a lowercase letter. To provide public access to these fields, you can define getter and setter methods:

func (p *Person) GetName() string {
	return p.name
}

func (p *Person) SetName(name string) {
	p.name = name
}

func (p *Person) GetAge() int {
	return p.age
}

func (p *Person) SetAge(age int) {
	p.age = age
}

Now, other parts of the program can create Person objects and access their name and age fields only through these getter and setter methods, which provides encapsulation.

2. Abstraction. Abstraction in Go can be achieved through the use of interfaces. An interface defines a set of methods that a type must implement in order to satisfy the interface. By programming to an interface instead of a concrete type, you can abstract away the implementation details of a particular object and focus on its behavior.

For example, consider the following interface:

type Shape interface {
	Area() float64
}

This interface defines a single method, Area(), which calculates the area of a shape. Any type that implements this method can be used wherever a Shape is expected, without needing to know the specifics of the implementing type.

3. Inheritance. In Go, inheritance is not supported in the traditional sense. Instead, Go uses composition to achieve similar functionality. A struct can embed another struct, allowing it to inherit its fields and methods.

For example, consider the following struct:

type Animal struct {
	name string
}

type Dog struct {
	Animal
	breed string
}

Here, the Dog struct embeds the Animal struct, which means it inherits its name field. The Dog struct also has a breed field of its own. Now, any method that operates on an Animal can also operate on a Dog, because a Dog is an Animal with some additional fields.

4. Polymorphism. Polymorphism in Go can be achieved through interfaces. Since Go is a statically typed language, the type of a variable must be known at compile time. However, by using interfaces, you can write code that can operate on different types that satisfy the same interface, without needing to know their specific type at compile time.

For example, consider the Shape interface we defined earlier. We can write a function that takes a Shape and calculates its area, without needing to know the specific type of shape:

func PrintArea(s Shape) {
	fmt.Println("Area of shape is:", s.Area())
}

Now, we can call this function with any type that implements the Area() method, such as a Circle, Rectangle, or Triangle, and it will calculate the area of that shape. This is polymorphism in action.

All posts