Programming is a creative task: there is no right or wrong way to solve a problem, in the same way, that there is no right or wrong way to paint a picture.
In this article, I will walk you through how I did my AltSchool Project. We'll learn about some OOP Concepts - Encapsulation, Abstraction, Inheritance, and Polymorphism.
But before I get started, let me brief you on what the project is about...
John has just opened up his car selling shop, to sell different cars. He gets the cars he needs to sell from different people and they all bring it to him. He needs to manage the list of cars he has, attach a price to them, and put them on display to be sold, basically John needs an inventory to manage cars & to manage sales. For instance,
He needs to see the number of cars that are left to be sold
He needs to see the sum of the prices of the cars left
He needs to see the number of cars he has sold
Sum total of the prices of cars he has sold
A list of orders that for the sales he made
Using the knowledge of OOP in Go, Build simple classes for the following “objects”
● Car
● Product
● Store
The Car class can have any car attributes you can think of.
The Product class should have attributes of a product i.e (theproduct, quantityofthe
productinstock,priceoftheproduct).
A car is a product of the store, but there can be other products so the attribute of the car can be promoted to the Product. The Product class should have methods to display a product, and a method to display the status of a product if it is still in stock or not.
The Store class should have attributes like
● Number of products in the store that are still up for sale
● Adding an Item to the store
● Listing all product items in the store
● Sell an item
● Show a list of sold items and the total price
So basically we'll be building a mini-ecommerce platform that will help John make sales and at the same time keep track of his sales.
Let me point out a few things, though Car is the main Product John deals on, he sells other Car accessories such as headlights, tyres etc so our Car class here will cover for all items John sells.
Defining the deliverables or functionalities of this app will be our first task. We’ll do this by creating a Store Interface. Interface basically helps us define a set of attributes or behaviors that a class implements. So instead of creating a function for each type of Product(Camry Car, Tyres, Car Headlights etc), whatever form the Product class takes, they'll be able to extend the interface functions. Attributes like "adding an item to the store" , "selling an item" will be common to any product whether an actual car or car accessories hence the need for interfaces. Interfaces is one way Go implements Polymorphism – one of the concept in Objected Oriented Programming.
Here is the Store definition:
type Store interface {
AddProduct(prod models.Product) models.Product
SellProduct(prod models.Product) models.Product
ProductList() []models.Product
OnSaleProducts() []models.Product
SoldProductList() []models.Product
OnSaleProductPriceTotal() float64
SoldProductPriceTotal() float64
DisplayStatus() string
}
Next step is to create Car, and Product class. Go does not support the actual Class keyword as in other languages like JavaScript, so we'll be using struct to define each of this classes. Like Class/Object in JavaScript and Dictionary in python, Go’s structs are typed collections of fields. They’re useful for grouping data together to form records.
So in case of Car and Product collection, the class will be defined as below:
type Car struct {
Id string
Name string
Model string
Price float64
IsCarType bool
DateAdded string
Color string
}
type Product struct {
Id string
Item Car
QtyInStock uint64
TotalPrice float64
OutOfStock bool
}
While declaring the Car and Product class, I capitalized "C" and "P" as well as the first letter for each of the field in each collection to make it accessible aside that package/file. Instead of "public" and "private" keyword like in other language, use of uppercase and lowercase for the first letter of any keyword is Go's way of encapsulation. Also, if you note, I used the "Car" struct as the type for "Item" in the "Product" struct, that's one way of implementing Inheritance(The Product class inherited the attributes of the Car class).
Now let’s extend the methods we defined in the Store Interfaces, that way our program can know what each method is supposed to do.
var products []models.Product
var availableProducts = products
var soldProducts []models.Product
func (product Product) AddProduct(prod models.Product) models.Product {
productExists := false
index := 0
for i, item := range availableProducts {
if item.Item.Name == prod.Item.Name && item.Item.Model == prod.Item.Model {
productExists = true
index = i
break
}
}
if productExists {
availableProducts[index].QtyInStock += 1
availableProducts[index].TotalPrice += prod.Item.Price
} else {
prod.Id = strconv.Itoa(rand.Intn(1000000000))
prod.TotalPrice = prod.Item.Price * float64(prod.QtyInStock)
prod.OutOfStock = false
products = append(products, prod)
availableProducts = append(availableProducts, prod)
}
fmt.Println("Product added successfully!")
return prod
}
func (product Product) SellProduct(prod models.Product) models.Product {
//availableProducts := availProductList
isEqual := false
greaterThanOne := false
index := 0
for i, item := range availableProducts {
if item.Item.Id == prod.Item.Id {
isEqual = true
index = i
if item.QtyInStock > 1 {
greaterThanOne = true
}
break
}
}
if isEqual {
if greaterThanOne {
availableProducts[index].QtyInStock -= 1
availableProducts[index].TotalPrice -= prod.Item.Price
availableProducts[index].OutOfStock = false
for _, item := range products {
if item.Id == prod.Id {
item.QtyInStock -= 1
item.TotalPrice -= prod.Item.Price
item.OutOfStock = false
break
}
}
} else {
availableProducts = append(availableProducts[:index-1], availableProducts[index+1:]...)
for _, item := range products {
if item.Id == prod.Id {
item.OutOfStock = true
break
}
}
productExists := false
index := 0
for i, item := range soldProducts {
if item.Item.Name == prod.Item.Name && item.Item.Model == prod.Item.Model {
productExists = true
index = i
break
}
}
if productExists {
soldProducts[index].QtyInStock += 1
soldProducts[index].TotalPrice += prod.Item.Price
} else {
prod.TotalPrice = prod.Item.Price * float64(prod.QtyInStock)
soldProducts = append(soldProducts, prod)
}
}
}
fmt.Println("Sale successful!")
return prod
}
func (product Product) OnSaleProductPriceTotal() float64 {
var totalPrice float64
for _, item := range availableProducts {
totalPrice += item.TotalPrice
}
return totalPrice
}
func (product Product) DisplayStatus() string {
var status string
for _, item := range products {
if item.OutOfStock == false {
status = "Still on sale!"
} else {
status = "Out of stock!"
}
}
return status
}
func (product Product) SoldProductPriceTotal() float64 {
var totalPrice float64
for _, item := range soldProducts {
totalPrice += item.TotalPrice
}
return totalPrice
}
func (product Product) ProductList() []models.Product {
return products
}
func (product Product) SoldProductList() []models.Product {
return soldProducts
}
func (product Product) OnSaleProducts() []models.Product {
return availableProducts
}
So far we’ve been able to create a set of classes and functions that will help John record and track his sales. We learnt about basic types such as Struct and Interfaces as well as some OOP concepts in Go.
Hopefully, I’ll write another article on other Go types like maps, pointers as well as how Go implements concepts like Constructors, Abstraction etc. Meanwhile do well to drop any questions on the comment section.
Thank You.
Top comments (0)