Getting familiar with OOPs concept in Go and understanding how Go achieves these principles in its own exceptional way
You can see above that there is an alluring red heavenly body that looks and describes a lot more than this picture in this darkness of the universe with millions of stars and planets away from it. Well, we can also relate the same to our topic today like the universe is a big class of objects means the sun, planets, moons, asteroids, etc, are all objects of that class. In fact, the moonlight also plays a role in inheritance the moonlight which is actually dependent on the sun’s light. Hence, we can relate OOP’s concepts to a lot of things. So, let’s get a bit more familiar in respect with Go.
OOPs stands for Object-Oriented Programming Systems and are the type of programming in which we need to define the data structure for the data type and the certain operation to modularize our program structure. For more, you can refer to this link: https://en.wikipedia.org/wiki/Object-oriented_programming
We need OOPs when we need to modularize our complex code structure, make it more reliable, and maintainable, provide a good framework for code libraries, etc.
Let’s consider Go to be a light object-oriented programming language because of Go's simplicity. Go use the same alike concepts of OOPs but not all in one go. First of all, Go is not an OOP language and it is not designed to be like that because the principles of OOPs are designed to be consists of class and object structure to maintain the code infrastructure via implementing super class, abstract class, constructors, objects, derived class, and destructors, etc. Well, there is a lot to that. Talking about Go, it just implements its OOPs structure in its own way. Well, this debate can go long, but here’s an official FAQ answer available on this link: https://go.dev/doc/faq#Is_Go_an_object-oriented_language. Go check it out.
Here are some concepts of OOPs below with respect to Go, so let’s try to get familiar with them.
In simpler terms encapsulation means if we have single entity data that is written inside any class or package it is hidden for another class or for the outside world whereas abstraction means to hide unnecessary information
In Go, we use this principle at package level because it doesn’t provide access modifiers like private, public, and protected. It also plays a role in variables, structs, methods, and functions, so if you say, for example, declare a function with the capital letter that function could be easily invoked in the current package as well as in another package hence it makes it publicly available in code structure whereas if you declare a function with a small letter it would only be available to that particular package, hence making it more private and a bit secure.
Hence, from the above example, you can see how functions can become private and public according to case sensitivity.
In terms of OOPs, encapsulation and abstraction are more than just data hiding and access specification it bring more features to the classes and interfaces, but in the case of Go, it just uses the lighter version of both concepts.
In brief, inheritance means to create new classes(subclasses or derived classes) from existing base(parent) classes and achieve code reusability. In Go, there is no such thing as inheritance but there is composition to achieve structure inheritance via struct-embedding means to embed fields of one struct to another struct. You can get to know more about struct-embedding by this link: https://gobyexample.com/struct-embedding
Go only supports composition if we say it in terms of inheritance. While inheritance is more than just composition as people who are having experience in OOPs languages like JAVA, C++, etc.
Polymorphism is the oop concept in which an object is capable of molding into multiple forms just like three spiderman’s in our case from a different dimension with different forms but the entity is the same.
In Go, we can achieve polymorphism via implementing interfaces in Go. Interfaces work as a collection of methods. Let’s get more familiar with an example.
Hence, in the above example, as you can see the Developer struct implements the Tasks interface by defining methods like BugFix and Improvement. I have written this example because we developers are much more friendly with these terms in our days while getting assigned different versions of tasks like bugfix, improvements, hotfix, etc.
Enum is a special data type with enumerated data which consists of a set of elements. Mostly the enumerated data is of constant type in many languages.
In the case of Go, we can create enums and define constant variables accordingly by declaring iota to the first variable in a series of it. The iota keyword represents the integer constant from zero.
Java = iota
)Output: 0 1 2 3
There are some more examples with which we can get to know more about how iota works differently with several ways of initialization.
Java = iota
)Output: 0 1 3
Above, as you can see the _ skips the value in the enum counter
Java = iota
Rust = iota
)Output1: 0 1
Output2: 0 1
Above, as you can see if you define the different enumerated typed constants they will have their own increment values starting from zero.
So, that’s it about OOPs in Go. In an upcoming article, I will write that how we can achieve functional programming in Go, and also I will be coming up with system design principles.