An Object Oriented Programming Language - Practical Go Lessons-39

You might also like

Download as pdf or txt
Download as pdf or txt
You are on page 1of 12

An object oriented programming language ? - Practical Go Lessons https://www.practical-go-lessons.

com/chap-39-an-object-oriented-programming-language

Chapter 39: An object oriented programming language ?

1 What will you learn in this chapter?


• What are object-oriented languages?

• What are common characteristics shared by object-oriented languages?

2 Technical concepts covered


• abstraction

• polymorphism

• inheritance

• composition

• class

• object

• type struct

• type embedding

3 Introduction
If you are new to programming, you might not have been exposed to “object-oriented programming”. If you are a veteran programmer,
there is a great chance that you have developed programs with an object-oriented language: you know what objects are, what encapsulation
means ...etc.

The purpose of this section is to review all the characteristics of an object-oriented language. By doing so, we will attempt to understand why
Go differs from those traditional languages.

Most of my students are afraid of the terms and notions linked to object-oriented programming. Do not be impressed by those complicated
terms.

The paper and the digital edition of this book are available here. ×
I also filmed a video course to build a real world project with Go.

4 What is an object-oriented language


The concept is not new.

1 of 12 02/01/2023, 02:24
An object oriented programming language ? - Practical Go Lessons https://www.practical-go-lessons.com/chap-39-an-object-oriented-programming-language

Back in 1966, the SIMULA language was object-oriented, then SMALLTALK-80 was first released in 1980. This last language was used a lot in
schools to teach students the basics of object design.

What is the definition of this type of language? An object-oriented language is “a programming language that allows the user to express a
program in term of objects and messages between those objects” (IEEE definition from [@institute1990ieee]).

The definition highlight that it’s a category of programming languages that offers to the users objects and a way to pass messages between
objects.

Object-oriented languages share some common characteristics :

• Classes and objects are program building blocks.

• It offers a certain level of abstraction

• It provides encapsulation mechanisms

• Polymorphism is possible

• Classes can inherit from one another

Let’s iterate over each of those characteristics to determine if Go can be considered as an Object-Oriented Programming Language.

5 Class, object & instance


This section will give some basic definitions of class, object, instance. Those are general definitions that apply to most object-oriented
programming languages

5.0.0.1 Class
• This is a user-defined programming entity

• It defines a set of attributes (each attribute has a type)

• Attributes are also called properties, fields, data members

• It defines methods (behaviors and operations) and their implementation.

• Methods and attributes have a specific “visibility”. Attributes and methods can be called only in specific conditions.

• Often, classes have a “constructor”, this is a method that is designed to create an object.

◦ Constructors are used to initialize the object “state”, ie. initialize values of attributes to specific values.

Here is an example of a class in C++ :

// C++
#include <iostream>
using namespace std;

class Teacher {
public:
string firstname; // Attribute
string lastname; // Attribute
void sayHello() { // Method
cout << "Hello World!";
}
};

int main() {
Teacher myTeacher;
myTeacher.sayHello();
return 0;
}

5.0.0.2 Objects
• Objects are created during program runtime. They are “run-time entit[ies]”[@gamma1995design]

• A call to the class constructor creates an object.

• An object is also called “an instance”

2 of 12 02/01/2023, 02:24
An object oriented programming language ? - Practical Go Lessons https://www.practical-go-lessons.com/chap-39-an-object-oriented-programming-language

• The process of creating an object is called “instanciation”.

6 Go classes ?
Go has “types” but no classes. A type specifies : “a set of values”

“operations and methods specific to those values” Struct types allow you to define a set of fields with a name and a type. Let’s take the
example of a teacher object :

// object-oriented/classes/main.go

type Teacher struct {


id int
firstname string
lastname string
}

We define the type Teacher that has three fields: id of type int , firstname and lastname of type string .

We can also attach methods on this type :

func (t *Teacher) sayHiToClass(){


fmt.Printf("Hi class my name is %s %s", t.firstname, t.lastname)
}

We have defined a type struct with a data structure and attached methods. Let’s create an instance t of that object :

t := Teacher{12, "John", "Doe"}

Then we can use the methods defined on the object with that particular instance :

t.sayHiToClass()

You can also create a type based on another type :

type StatusCode int

And this type can also have methods :

func (s *StatusCode) String() string {


return fmt.Sprintf("Status Code %d",s)
}

In this case the set of values StatusCode is limited to integers

• Go type structs are close to classes

• Type structs have fields

• You can define methods attached to types

• Compared to other languages, there is no “constructors” out of the box.

• Fields of a type struct are automatically initialized by Go (to the field type’s zero value).

• In place of constructors, some libraries define a New function :

Here is a New function from the module github.com/gin-gonic/gin :

package gin

// New returns a new blank Engine instance without any middleware attached.
// ...
func New() *Engine {
//...
}

Here is a New function defined into the standard package math/rand :

3 of 12 02/01/2023, 02:24
An object oriented programming language ? - Practical Go Lessons https://www.practical-go-lessons.com/chap-39-an-object-oriented-programming-language

package rand

// New returns a new Rand that uses random values from src
// to generate other random values.
func New(src Source) *Rand {
//..
}

And another one from the doc package :

package doc

//...

func New(pkg *ast.Package, importPath string, mode Mode) *Package {


//...
}

• You can note that, generally, New function returns a pointer

• It’s also common to have a New function that returns a pointer AND an error

7 Abstraction
Another important concept of object-oriented programming is abstraction.

When we are building our code, we call methods or functions to perform a specific operation : u.store()

Here we are telling our program to call the method store . It does not require you to know about how the method is implemented (how it is
coded inside).

• The term abstraction comes from Latin abstractio.This term conveys the idea of separation, of taking away something.

• Function and methods call are taking away the concrete implementation, the complex details.

• The main advantage of hiding the implementation details is that you can change it without impacting the function call (if you do not
change the function signature).

The paper and the digital edition of this book are available here. ×
I also filmed a video course to build a real world project with Go.

8 Encapsulation
Encapsulation comes from the Latin term “capsula” which means “a small box”. In the French language, the term “capsule” refers to
something that is boxed. In biology, this term is used to designate a cell’s membrane.

A capsule is a container in which you can box objects. Encapsulating something is equivalent to enclose it inside a capsule.

If we come back to computer science, encapsulation is a design technique used to group operations and data into isolated capsules of codes.
The access to those operations and data is regulated, and those “capsules” define external interfaces to interact with them.

An object-oriented programming language gives the developer the ability to encapsulate objects. Is it the case with Go? Can we encapsulate
things? Can we define strict external interfaces on packages?

The answer is yes! The concept of packages allows you to define a strict external interface.

8.0.0.1 Visibility
Let’s take an example. We define the packageA

4 of 12 02/01/2023, 02:24
An object oriented programming language ? - Practical Go Lessons https://www.practical-go-lessons.com/chap-39-an-object-oriented-programming-language

// object-oriented/encapsulation/packageA/packageA.go
package packageA

import "fmt"

func DoSomething() {
fmt.Println("do something")
}

func onePrivateFunction() {
//...
}

func anotherPrivateFunction() {
//...
}

func nothingToSeeHere() {
//..
}

The packageA defines only a public function DoSomething . The outside world can use this function, but it will not compile if you try to
access to a private function ( onePrivateFunction , anotherPrivateFunction ...). There is no public or private keyword in the language; the
visibility is defined by the case of the first letter of the defined elements (methods, types, constants ...)

8.0.0.2 Advantages of encapsulation


• It hides the implementation to the user of the package.

• It allows you to change the implementation without being worried about breaking something in your user’s code. You can only break
something if you change one of your package’s exported (public) elements.

• Maintenance and refactoring are easier to perform. Internal changes will seldom affect clients.

9 Polymorphism
Polymorphism is the capacity for something to have several forms. The words come from the term poly (which means several) and
“morphism” which design forms, shapes of something.

How to apply that to a programming language? To understand polymorphism, you have to focus on operations, i.e., methods.

A system is said to be polymorphic if “the same operation can behave differently in different classes”[@rumbaugh1991object].

Let’s refine our teacher example. A school teacher is not the same as a university teacher; therefore we can define two different “classes”, two
different struct types. The SchoolTeacher type struct :

type SchoolTeacher struct {


id int
firstname string
lastname string
}

And the UniversityTeacher type struct :

type UniversityTeacher struct {


id int
firstname string
lastname string
department string
specialty string
}

The second type of teacher has more fields for its specialty and department.

Next, we will define the same operation for the two types of teachers :

func (t SchoolTeacher) SayHiToClass() {


fmt.Printf("Hi class my name is %s %s\n", t.firstname, t.lastname)
}

5 of 12 02/01/2023, 02:24
An object oriented programming language ? - Practical Go Lessons https://www.practical-go-lessons.com/chap-39-an-object-oriented-programming-language

And for the other type, the implementation is slightly different :

func (t UniversityTeacher) SayHiToClass() {


fmt.Printf("Hi dear students my name is %s %s I will teach you %s\n", t.firstname, t.lastname, t.specialty)
}

The university teacher always specifies his field and department when he says hi to class. Whereas the school teacher doesn’t.

Here we have the same operation defined on two different types; we can define an interface Teacher :

type Teacher interface {


SayHiToClass()
}

Automatically the types SchoolTeacher and UniversityTeacher will implement the interface (you do not have to specify it in the source
code). Let’s create a slice composed of two objects :

john := UniversityTeacher{id:12,firstname:"John",lastname:"Doe",department:"Science",specialty:"Biology"}
marc := SchoolTeacher{id:23,firstname:"Marc",lastname:"Chair"}

John is a university teacher in biology; Marc educates children. Their job is not the same, but they share a common operation: the class
greeting operation. Therefore they implement the Teacher interface type. We can group those two objects in a slice composed of Teacher
objects :

teachers := []Teacher{john,marc}

We can then iterate over the slice and make them say hi to their class in their specific style :

// object-oriented/polymorphism/main.go
func main() {
//...
teachers := []Teacher{john, marc}
for _, t := range teachers {
t.SayHiToClass()
}
}

In this last code listing, we have discovered the power of polymorphism :

• Go can find which method to call based on the type of t.

• The same interface type designs different implementations Teacher

10 Inheritance
A child may inherit the genetic properties of its ancestors. But we cannot reduce children to their ancestors. When they grow up, they will
build their specific properties.

The same inheritance concept applies to classes in object-oriented programming. When you create a complex application, often the objects
identified share some common properties and operations.

For instance, every teacher has a name, a surname, a date of birth, an address, etc. School teachers and university teachers have both those
properties. Why not create a super object that will hold those common properties and share them with the subclasses?

That’s the idea of inheritance. Objects will define their unique properties and operations and inherit its ancestor. This will reduce code
repetition. Shared properties are only defined into the super object, just once.

Is it possible with Go? The answer is no. We will see an important design concept: type embedding. The main objective of this section is to
see if we can see type embedding as a form ofinheritance.

10.1 Single type embedding


You can embed a type into another type. Let’s take our previous example. We have a type struct human with two fields :

type Human struct {


firstname string
lastname string
}

6 of 12 02/01/2023, 02:24
An object oriented programming language ? - Practical Go Lessons https://www.practical-go-lessons.com/chap-39-an-object-oriented-programming-language

This represents a Human. We add him the capability to walk :

func (t Human) Walk() {


fmt.Printf("I walk...\n")
}

A school teacher and a university teacher are both humans; we can embed the type Human into those two types :

type SchoolTeacher struct {


Human
}
type UniversityTeacher struct {
Human
department string
specialty string
}

To do this, we just add the name of the type as a new field (without a name).

By doing so, we can define our two teachers :

john := UniversityTeacher{Human: Human{ firstname: "John", lastname: "Doe"}, department: "Science", specialty: "Biology"}
marc := SchoolTeacher{Human: Human{firstname:"Marc",lastname:"Chair"}}

We can call the method Walk on john and marc :

// object-oriented/inheritance/single-type-embedding/main.go
//...
func main() {
john.Human.Walk()
marc.Human.Walk()
// or
john.Walk()
marc.Walk()
}

Which will output :

I walk...
I walk...

10.2 Multiple type embedding


You are not limited to one type embed into a type struct. You can embed several types. Let’s introduce the type Researcher :

type Researcher struct {


fieldOfResearch string
numberOfPhdStudents int
}

A Researcher has a field of research and a certain number of Ph.D. students that he has to follow. University teachers are also Researchers.
We can embed the type Researcher into the type UniversityTeacher :

// object-oriented/inheritance/multiple-type-Embedding/main.go

type UniversityTeacher struct {


Human
Researcher
department string
specialty string
}

10.3 Name conflicts


But there is an important limitation to type Embedding: name conflicts. If you want to embed two types that come from different packages
but share the same name, your program will not compile. Let’s take an example. You have two packages packageA and packageB each of
them declares a type called MyType :

7 of 12 02/01/2023, 02:24
An object oriented programming language ? - Practical Go Lessons https://www.practical-go-lessons.com/chap-39-an-object-oriented-programming-language

package packageA

type MyType struct {


id int
}

package packageB

type MyType struct {


id int
}

Now in your main package, you define a package MyOtherType wich embed both types :

type MyOtherType struct {


packageA.MyType
packageB.MyType
}

There is a duplication of a filed name. The two first fields are embed fields; therefore, their name is both MyType in the type struct
MyOtherType . Having two fields with the same name is not possible. Your program will not compile :

typeEmbedding/nameClash/main.go:10:10: duplicate field MyType

Compilation finished with exit code 2

10.4 Direct access to properties and operations


In other object-oriented languages, a class B that inherits from A can access directly all the properties and operation defined in A.

What does it mean? Let’s take the example of PHP. We define a class A that has the method sayHi (public means that the outside world
can access it, it’s like a method name starting with an uppercase character) :

// PHP Code
class A
{
public function sayHi()
{
echo 'Hi !';
}

Then in the same script, we define the class B that inherits from the class A . The keyword in PHP is extends :

// PHP Code
class B extends A
{
public function sayGoodbye()
{
echo 'Goodbye !';
}
}

The class B is an heir of A . Therefore we can access the methods of directly A with an object of type B :

// PHP Code
// $b is a new instance of class B
$b = new B();
// we call the method sayHi, which is defined in class A
$b->sayHi();
// We call the method sayGoodbye defined in the class B
$b->sayGoodbye();

Here we have direct access to properties and operations defined on A from B.

We can access an embedded type’s properties directly with type embedding. We can write :

john.Walk()

8 of 12 02/01/2023, 02:24
An object oriented programming language ? - Practical Go Lessons https://www.practical-go-lessons.com/chap-39-an-object-oriented-programming-language

We can also write :

john.Human.Walk()

10.5 Composition over inheritance


Type embedding and inheritance have the same goal: avoid code repetition and maximize code reuse. But composition and inheritance are
two very different designs. Go approach is composition over inheritance.

I will write the distinction made by the authors of the very famous Design Patterns: Elements of Reusable Object-Oriented Software
([@gamma1995design]):

• Inheritance is a “white-box reuse” strategy : The heir classes have access to internal properties of their ancestors; internal properties
and operations can be visible to the heir class.

• Composition is a “black-box reuse” strategy : The classes are composed together, the type A that embed a type B do not have
access to all the internal properties and operations. Public fields and methods are accessible; private ones aren’t.

Let’s take an example. We have a cart that defines the type struct Cart :

package cart

type Cart struct {


ID string
locked bool
}

This type struct has two fields named ID and locked . The field ID is exported. The field named locked is not accessible from another
package.

In our main program, we create another type struct named User :

package main

type User struct {


cart.Cart
}

The type cart.Cart is embedded into User . If we create a variable of type User we can only access the exported fields from cart.Cart
:

func main() {
u := User{}
fmt.Println(u.Cart.ID)
}

If we call

fmt.Println(u.Cart.locked)

our program will not compile with the following error message :

typeEmbedding/blackBoxReuse/main.go:17:27: u.Cart.locked undefined (cannot refer to unexported field or method private)

10.6 Advantages of composition over inheritance


• In the inheritance model, the heir class can access the ancestor class’s internals. The ancestor internals can be visible to the heir; the
encapsulation rule is somewhat broken. Whereas with composition, you cannot access the ancestor class’s hidden parts. This technique
ensures that your structs’ users will only use the exported methods and fields.

• Composition is generally simpler than inheritance. If you are an experienced developer, you might have been confronted with an
object-oriented design where inheritance is overly used. In such cases, the project is harder to understand, and newcomers have to
spend hours with senior developers to understand the graph of classes.

11 Test yourself
11.1 Questions
1. Generally, what is (are) the return type(s) of New functions ?

9 of 12 02/01/2023, 02:24
An object oriented programming language ? - Practical Go Lessons https://www.practical-go-lessons.com/chap-39-an-object-oriented-programming-language

2. What is encapsulation? Give an example in Go.

3. What is polymorphism? Explain it using your own words.

4. True or False. A Go type can inherit from another type.

11.2 Answers
1. Generally, what is (are) the return type(s) of New functions ?

1. A pointer

2. Optionally an error

2. What is encapsulation? Give an example.

1. Encapsulation is a design technique used to group operations and data into isolated “capsules” of codes.

2. Isolated = access to data and methods is restricted.

3. A variable, constant, type, function, or method defined in a Go package is accessible in another package only if it’s exported.

4. Ex: see question 4 snippet below.

5. The type Cart is exported. The function total is not exported. The function New is exported

6. From another package, only Cart and New are accessible

3. What is polymorphism? Explain it using your own words.

1. The word polymorphic designates an entity that can have different forms.

2. Polymorphism is achieved when a single symbol can represent different types.

3. An interface type can represent different types (implementations).

4. True or False. A Go type can inherit from another type.

1. False.

2. There is no inheritance mechanism in Go.

3. However, Go allows the composition of types

4. You can embed a type in another type.

// question 4 snippet
package cart

//...

type Cart struct {


ID string
Items
}

func total() {
//...
}

func New() *Cart {


//...
}

The paper and the digital edition of this book are available here. ×
I also filmed a video course to build a real world project with Go.

12 Key Takeaways
• An object-oriented language is “a programming language that allows the user to express a program in term of objects and messages
between those objects”[@institute1990ieee]. Objects are instances of classes.

10 of 12 02/01/2023, 02:24
An object oriented programming language ? - Practical Go Lessons https://www.practical-go-lessons.com/chap-39-an-object-oriented-programming-language

◦ A class is a user-defined programming entity with behaviors and methods.

◦ In some languages, you will need to define constructors. Which are specific methods intended to initialize an object.

◦ An object encapsulates data and behaviors (methods)

• An object-oriented language has the following characteristics :

◦ Classes and objects are program building blocks.

◦ It offers a certain level of abstraction

◦ It provides encapsulation mechanisms

◦ Polymorphism is possible

◦ Classes can inherit from one another

• Go has types but no classes.

◦ A type specify a “set of values” along with “methods specific to those values”

◦ Some libraries define New functions that we can assimilate as “constructors”.

• Go offers “abstraction” to developers. For instance: you do not need to know the actual implementation of a method to call it.

• “Encapsulation” is a characteristic of Object-Oriented languages

• Go types, variables, and constants can be exported, making them available from another package.

◦ Thanks to this mechanism, the code can be “encapsulated”. Access to implementation details can be forbidden to the caller.
• Polymorphism is achieved when a single symbol can represent different types.

◦ An interface type can represent different types (implementations).


• There is no inheritance mechanism in Go. However, types can be composed together via type embedding

◦ Inheritance is a “white-box reuse” strategy : The heir classes have access to all internal properties of their ancestors, all internal
properties and operations are visible to the heir class.

◦ Composition is a “black-box reuse” strategy : The classes are composed together, the type A that embed a type B do not
have access to all the internal properties and operations. Public fields and methods are accessible; private ones aren’t.

package main

type User struct {


// Cart is embedded into type User
// this is called composition
cart.Cart
}
func main() {
u := User{}
fmt.Println(u.Cart.ID)
}

Bibliography
• [institute1990ieee] Electrical, Institute of, and Electronics Engineers. 1990. “IEEE Standard Glossary of Software Engineering Terminology:
Approved September 28, 1990, IEEE Standards Board.” In. Inst. of Electrical; Electronics Engineers.
• [gamma1995design] Gamma, Erich. 1995. Design Patterns: Elements of Reusable Object-Oriented Software. Pearson Education India.
• [rumbaugh1991object] Rumbaugh, James, Michael Blaha, William Premerlani, Frederick Eddy, William E. Lorensen, and others. 1991.
Object-Oriented Modeling and Design. Vol. 199. 1. Prentice-hall Englewood Cliffs, NJ.
• [gamma1995design] Gamma, Erich. 1995. Design Patterns: Elements of Reusable Object-Oriented Software. Pearson Education India.
• [institute1990ieee] Electrical, Institute of, and Electronics Engineers. 1990. “IEEE Standard Glossary of Software Engineering Terminology:
Approved September 28, 1990, IEEE Standards Board.” In. Inst. of Electrical; Electronics Engineers.

Previous Next

Generics Upgrading or Downgrading Go

Table of contents

11 of 12 02/01/2023, 02:24
An object oriented programming language ? - Practical Go Lessons https://www.practical-go-lessons.com/chap-39-an-object-oriented-programming-language

Did you spot an error ? Want to give me feedback ? Here is the feedback page! ×

Newsletter:
Like what you read ? Subscribe to the newsletter.

I will keep you informed about the book updates.

@ my@email.com

Practical Go Lessons
By Maximilien Andile
Copyright (c) 2023
Follow me Contents
Posts
Book
Support the author Video Tutorial

About
The author
Legal Notice
Feedback
Buy paper or digital copy
Terms and Conditions

12 of 12 02/01/2023, 02:24

You might also like