💻 Tech
In Go, there’s a concept of embedding that allows an outer type to access properties and methods by an inner type. This is different from other languages’ concept of inheritance where there’s a subtype. Go only does “promotion” of properties and methods, and it does not make one type a type of another.
In the code below, employee
is embedded in department
, that’s why an object of type department
can access method report()
of employee
because the properties and methods are promoted from inner type (employee) to the outer type (department). We can see it in three ways:
- Direct access from
department
- Direct access from
employee
- Access via a polymorphic function
The polymorphic function already knows that the function is from the employee
because, again, the methods are promoted to the outer type even though we passed a copy of department
to the function. What will happen if two structs have the same implementation? See the 2nd version below.
type employee struct{}
type department struct {
employee
}
func (employee) report() {
fmt.Println("employee reporting")
}
type someinterface interface {
report()
}
func main() {
d := department{
employee: employee{},
}
d.report()
d.employee.report()
report(&d)
}
func report(s someinterface) {
s.report()
}
employee reporting
employee reporting
employee reporting
In the 2nd version of the code below, department
has its own implementation. In the output, we can see that the outer type (department
) takes precendence over the implementation of the inner type (employee
). But if you access the inner type directly, you can use its implementation. In addition, the polymorphic function uses the outer type’s implementation. In other words, if there are implementations in the outer and inner types, accessing the method via outer type and polymorphic function will prioritize the outer type’s implementation.
type employee struct{}
type department struct {
employee
}
func (employee) report() {
fmt.Println("employee reporting")
}
func (department) report() {
fmt.Println("department reporting")
}
type someinterface interface {
report()
}
func main() {
d := department{
employee: employee{},
}
d.report()
d.employee.report()
report(&d)
}
func report(s someinterface) {
s.report()
}
department reporting
employee reporting
department reporting