Yes and no. Although Go has types and methods and allows an object-oriented style of programming, there is no type hierarchy. This is in contrast to most object-oriented languages like C++, Java, C#, Scala, and even dynamic languages like Python and Ruby.
Go Object-Oriented Language Features:
- Structs – Structs are user-defined types. Struct types (with methods) serve similar purposes to classes in other languages.
- Methods – Methods are functions that operate on particular types. They have a receiver clause that mandates what type they operate on.
- Embedding – we can embed anonymous types inside each other. If we embed a nameless struct then the embedded struct provides its state (and methods) to the embedding struct directly.
- Interfaces – Interfaces are types that declare sets of methods. Similarly to interfaces in other languages, they have no implementation. Objects that implement all the interface methods automatically implement the interface. There is no inheritance or subclassing or “implements” keyword.
The Go way to implement:
- Encapsulation – Go encapsulates things at the package level. Names that start with a lowercase letter are only visible within that package. You can hide anything in a private package and just expose specific types, interfaces, and factory functions.
- Inheritance – composition by embedding an anonymous type is equivalent to implementation inheritance.
- Polymorphism – A variable of type interface can hold any value which implements the interface. This property of interfaces is used to achieve polymorphism in Go.
Consider:
package main
import (
"fmt"
)
// interface declaration
type Income interface {
calculate() int
source() string
}
// struct declaration
type FixedBilling struct {
projectName string
biddedAmount int
}
type TimeAndMaterial struct {
projectName string
noOfHours int
hourlyRate int
}
// interface implementation for FixedBilling
func (fb FixedBilling) calculate() int {
return fb.biddedAmount
}
func (fb FixedBilling) source() string {
return fb.projectName
}
// interface implementation for TimeAndMaterial
func (tm TimeAndMaterial) calculate() int {
return tm.noOfHours * tm.hourlyRate
}
func (tm TimeAndMaterial) source() string {
return tm.projectName
}
// using Polymorphism for calculation based
// on the array of variables of interface type
func calculateNetIncome(ic []Income) {
var netincome int = 0
for _, income := range ic {
fmt.Printf("Income From %s = $%d\n", income.source(), income.calculate())
netincome += income.calculate()
}
fmt.Printf("Net income of organisation = $%d", netincome)
}
func main() {
project1 := FixedBilling{projectName: "Project 1", biddedAmount: 5000}
project2 := FixedBilling{projectName: "Project 2", biddedAmount: 10000}
project3 := TimeAndMaterial{projectName: "Project 3", noOfHours: 160, hourlyRate: 25}
incomeStreams := []Income{project1, project2, project3}
calculateNetIncome(incomeStreams)
}