Lesson 6
Blending Programming Principles in Go: Encapsulation, Abstraction, Polymorphism, and Composition
Introduction and Lesson Goal

Today's mission involves leveraging various programming principles in Go to tackle complex tasks effectively. When principles like Encapsulation, Abstraction, Polymorphism, and Composition are blended, the resulting code becomes streamlined and easier to manage.

Our goal is to explore two real-world examples, demonstrating how these principles can seamlessly orchestrate solutions using structs, interfaces, and composition in Go.

Real-life Example 1: Building an Online Library System

We'll design an online library system to reinforce our understanding of Encapsulation and Polymorphism in Go. Encapsulation will help us guard the attributes of books, members, and transactions, ensuring controlled access. Polymorphism will illustrate its utility by enabling a single interface to represent different underlying forms, such as digital and print versions of books.

Go
1package main 2 3import ( 4 "fmt" 5) 6 7// Struct defining a library member 8type Member struct { 9 name string 10} 11 12// Method for a member to check out a book 13func (m *Member) CheckOutBook(book Book) { 14 fmt.Printf("%s checked out %s book %s.\n", m.name, book.GetBookType(), book.GetTitle()) 15} 16 17// Interface for different types of books 18type Book interface { 19 GetBookType() string 20 GetTitle() string 21} 22 23// Struct representing a digital book 24type DigitalBook struct { 25 title string 26} 27 28// Implementing Book interface for DigitalBook 29func (d DigitalBook) GetBookType() string { 30 return "Digital" 31} 32 33func (d DigitalBook) GetTitle() string { 34 return d.title 35} 36 37// Struct representing a physical book 38type PhysicalBook struct { 39 title string 40} 41 42// Implementing Book interface for PhysicalBook 43func (p PhysicalBook) GetBookType() string { 44 return "Physical" 45} 46 47func (p PhysicalBook) GetTitle() string { 48 return p.title 49} 50 51// Struct representing a library to manage members and books 52type Library struct { 53 members []Member 54 books []Book 55} 56 57// Method to add a member 58func (l *Library) AddMember(member Member) { 59 l.members = append(l.members, member) 60} 61 62// Method to add a book 63func (l *Library) AddBook(book Book) { 64 l.books = append(l.books, book) 65} 66 67func main() { 68 myLibrary := Library{} 69 70 alice := Member{"Alice"} 71 bob := Member{"Bob"} 72 73 myLibrary.AddMember(alice) 74 myLibrary.AddMember(bob) 75 76 digitalBook := DigitalBook{"The Go Handbook"} 77 physicalBook := PhysicalBook{"Learning Go Design Patterns"} 78 79 myLibrary.AddBook(digitalBook) 80 myLibrary.AddBook(physicalBook) 81 82 alice.CheckOutBook(digitalBook) // Prints: Alice checked out Digital book The Go Handbook. 83 bob.CheckOutBook(physicalBook) // Prints: Bob checked out Physical book Learning Go Design Patterns. 84}

In this code snippet, Encapsulation is demonstrated by using Go structs to contain member and book details. Polymorphism is illustrated by how both DigitalBook and PhysicalBook structs implement the Book interface, allowing them to be used interchangeably when identifying the type of a book. This setup shows how polymorphism in Go allows working with different types through common interface definitions.

  • Encapsulation secures member and book information within their respective structs.
  • Polymorphism permits uniform handling of different book types, enhancing system adaptability.
Real-life Example 2: Building a Shape Drawing Application

Now, we'll develop a shape-drawing application capable of rendering various shapes using Abstraction and Composition.

  • Abstraction reduces complexity in handling different shapes.
  • Composition facilitates the creation of composite shapes.

Here's how these principles translate into our shape-drawing application in Go:

Go
1package main 2 3import "fmt" 4 5// Interface defining a Shape 6type Shape interface { 7 Draw() 8} 9 10// Struct representing a Circle 11type Circle struct{} 12 13// Implementing Draw method for Circle 14func (c Circle) Draw() { 15 fmt.Println("Drawing a circle.") 16} 17 18// Struct representing a Square 19type Square struct{} 20 21// Implementing Draw method for Square 22func (s Square) Draw() { 23 fmt.Println("Drawing a square.") 24} 25 26// Struct for composing multiple shapes 27type ShapeComposite struct { 28 shapes []Shape 29} 30 31// Method to add a shape to the composite 32func (sc *ShapeComposite) AddShape(shape Shape) { 33 sc.shapes = append(sc.shapes, shape) 34} 35 36// Implementing Draw method for composite shapes 37func (sc ShapeComposite) Draw() { 38 for _, shape := range sc.shapes { 39 shape.Draw() 40 } 41} 42 43func main() { 44 circle := Circle{} 45 square := Square{} 46 47 // Drawing individual shapes 48 circle.Draw() // Output: Drawing a circle. 49 square.Draw() // Output: Drawing a square. 50 51 // Creating a ShapeComposite instance for composite shapes 52 compositeShape := ShapeComposite{} 53 54 // Adding individual shapes to the composite 55 compositeShape.AddShape(circle) 56 compositeShape.AddShape(square) 57 58 // Drawing the composite shape 59 compositeShape.Draw() 60 // Output: 61 // Drawing a circle. 62 // Drawing a square. 63}
  • Abstraction: Here, the Shape interface abstracts the specific details of drawing shapes, ensuring that all shapes conform to having a Draw() method. This interface acts as a blueprint for all shapes.

  • Composition: The ShapeComposite struct exemplifies composition by combining multiple shapes. It can hold and render multiple shapes as a single unit. Composition is effectively used to manage a group of shapes together.

Lesson Summary

Well done! You combined multiple programming principles using Go's unique features of structs and interfaces to tackle complex tasks. By examining real-world examples, we learned how these principles apply in Go. Now, it's time to practice these skills. Active coding will solidify concepts, turning knowledge into expertise. Let's start coding!

Enjoy this lesson? Now it's time to practice with Cosmo!
Practice is how you turn knowledge into actual skills.