# Composition and Embedding

Course: [Go](https://www.devtutorials.ai/learn/go) · Section: Types and OOP
Source: https://www.devtutorials.ai/learn/go/types-and-oop/composition-and-embedding

> Build bigger types from smaller ones: has-a composition, struct embedding with promoted fields and methods, method resolution, and why Go prefers composition over inheritance.

## What Is Composition?

**Composition** = building a bigger type by putting smaller types **inside** it.

- A `School` has an `Address`.
- A `Student` has a `Contact`.
- A `Library` has many `Book`s.

Each small type does one job. The big type joins them.

**Simple lesson:** composition builds big things out of small, ready-made parts.

### A Real-World Example

Think of building a school with toy blocks.

- One block set makes a **classroom**.
- Another makes a **playground**.
- Another makes a **library**.
- You put them together, and you have a **school**.
- If the library needs to change, you swap only that block.

Now the mapping:

- **Each block** = a small struct.
- **The school** = the big struct that contains them.
- **Swapping one block** = changing one part without touching the others.

Many languages use **inheritance**: a child class gets everything from a parent class.

Go has **no inheritance**. It uses **composition** and **embedding** instead.

## What You Will Learn

In this lesson, you will learn:

1. What composition is, and why Go prefers it.
2. The has-a relationship.
3. How struct embedding works, with promoted fields.
4. How embedded methods are promoted, and how Go picks which method to call.
5. How to build complex types from small parts.
6. How composition differs from inheritance.

## Composition Fundamentals

### Has-A Relationship

**Has-a relationship** = one type **has** another type as a part.

- A `Student` **has an** `Address`.
- A `Bus` **has a** `Driver`.
- If you can say "X has a Y", put a `Y` field inside `X`.

```go runnable title="A student has an address"
package main

import "fmt"

type Address struct {
	City    string
	PinCode string
}

type Student struct {
	Name string
	Home Address
}

func main() {
	s := Student{
		Name: "Asha",
		Home: Address{City: "Pune", PinCode: "411001"},
	}
	fmt.Println(s.Name, "lives in", s.Home.City)
}
```

```text
Asha lives in Pune
```

- `Home` is a normal **named field** of type `Address`.
- You reach its fields with two dots: `s.Home.City`.

### Why Composition Is Preferred in Go

- **Small parts are easy to understand** and test.
- **Parts can be reused** in many types: `Address` fits a `Student`, a `Teacher` and a `School`.
- **Changes stay local.** Changing `Address` does not break a family tree of classes.
- **No deep hierarchies** like "A extends B extends C extends D".

**Simple lesson:** if X has a Y, put a Y inside X.

## Struct Embedding

### Struct Embedding

**Embedding** = putting a type inside a struct **without a field name**.

```go
type Person struct {
	Name string
	Age  int
}

type Teacher struct {
	Person          // embedded: no field name
	Subject string
}
```

- `Person` is written alone, with no name in front.
- The embedded field's name is its type name: `Person`.

### Promoted Fields

**Promoted field** = a field of the embedded type that you can use directly on the outer type.

- `t.Name` is short for `t.Person.Name`.
- The data still lives inside the embedded `Person`.

### Reusing Functionality

```go runnable title="One Contact part, used twice"
package main

import "fmt"

type Contact struct {
	Phone string
	Email string
}

type Student struct {
	Name string
	Contact
}

type Teacher struct {
	Name string
	Contact
}

func main() {
	s := Student{"Ravi", Contact{"98450 11111", "ravi@gvs.edu"}}
	t := Teacher{"Mr. Khan", Contact{"98450 22222", "khan@gvs.edu"}}
	fmt.Println(s.Name, s.Phone)
	fmt.Println(t.Name, t.Email)
}
```

```text
Ravi 98450 11111
Mr. Khan khan@gvs.edu
```

- `Contact` is written once and reused in two types.

**Simple lesson:** embed a type with no field name, and its fields are promoted to the outer type.

## Promoted Methods

### Embedded Methods

Methods of the embedded type are promoted too.

```go runnable title="Methods are promoted"
package main

import "fmt"

type Logger struct {
	Prefix string
}

func (l Logger) Log(msg string) {
	fmt.Println(l.Prefix + msg)
}

type Library struct {
	Logger
	Books int
}

func main() {
	lib := Library{Logger: Logger{"[library] "}, Books: 1200}
	lib.Log("opened")
	lib.Log(fmt.Sprint(lib.Books, " books on the shelves"))
}
```

```text
[library] opened
[library] 1200 books on the shelves
```

- `Library` has no `Log` method of its own.
- `lib.Log(...)` calls `lib.Logger.Log(...)`.

### Method Resolution

**Method resolution** = how Go decides which method to run.

- Go first looks for the method on the **outer** type.
- If it is not there, Go looks in the **embedded** types.
- So an outer method with the same name **hides** the embedded one.

```go runnable title="The outer method wins"
package main

import "fmt"

type Animal struct {
	Name string
}

func (a Animal) Speak() string {
	return a.Name + " makes a sound"
}

type Dog struct {
	Animal
}

func (d Dog) Speak() string {
	return d.Name + " barks"
}

func main() {
	d := Dog{Animal{"Tommy"}}
	fmt.Println(d.Speak())
	fmt.Println(d.Animal.Speak())
}
```

```text
Tommy barks
Tommy makes a sound
```

- `d.Speak()` finds `Dog.Speak` first.
- `d.Animal.Speak()` reaches the hidden one on purpose.

### Ambiguous Names

If two embedded types have the same field or method, and the outer type does not, Go cannot choose:

```go
type Phone struct{ Number string }
type Locker struct{ Number string }

type Student struct {
	Phone
	Locker
}

// s.Number → error: ambiguous selector s.Number
// Use s.Phone.Number or s.Locker.Number instead.
```

Embedding is **not** inheritance.

The embedded value is a separate part. A method of `Animal` only sees the `Animal` fields. It does not know about `Dog`, and it cannot call `Dog`'s methods.

**Simple lesson:** embedded methods are promoted, and a method on the outer type always wins.

## Composition Patterns

### Building Complex Types

```go runnable title="A school bus built from parts"
package main

import "fmt"

type Engine struct {
	Fuel int
}

func (e *Engine) Refuel(litres int) {
	e.Fuel += litres
}

type Driver struct {
	Name string
}

type Route struct {
	Stops []string
}

func (r Route) Count() int {
	return len(r.Stops)
}

type SchoolBus struct {
	Number string
	Engine
	Route
	Driver Driver
}

func main() {
	bus := SchoolBus{
		Number: "GVS-04",
		Route:  Route{[]string{"Market", "Temple", "School"}},
		Driver: Driver{"Raju"},
	}
	bus.Refuel(40)
	fmt.Println(bus.Number, "driven by", bus.Driver.Name)
	fmt.Println("Fuel:", bus.Fuel, "Stops:", bus.Count())
}
```

```text
GVS-04 driven by Raju
Fuel: 40 Stops: 3
```

- `Engine` and `Route` are **embedded**: their fields and methods are promoted.
- `Driver` is a **named field**: you write `bus.Driver.Name`.
- `bus.Refuel(40)` changes the embedded engine, because `Refuel` has a pointer receiver.

**Simple lesson:** embed a part to share its abilities, and use a named field for a plain has-a part.

## Composition vs Inheritance

### Differences

| | Inheritance (other languages) | Composition (Go) |
|---|---|---|
| Relationship | is-a: a Dog **is an** Animal | has-a: a Bus **has an** Engine |
| How you get code | From a parent class | From parts you put inside |
| Change a parent | Every child may break | Only types that use that part are affected |
| Many sources | Often limited to one parent | Embed as many parts as you need |
| Shared behaviour | Through the class family | Through interfaces. See **Interfaces and Polymorphism** |

### Why Go Avoids Inheritance

- **Deep families of classes** become hard to change.
- **A change at the top** can break many classes below it.
- **"is-a" is often wrong** in real life: is a `Square` a `Rectangle`? It causes subtle bugs.
- Go's designers chose **simple parts plus interfaces** instead.

### Advantages of Composition

- **Flexible:** mix any parts.
- **Clear:** each part has one job.
- **Testable:** test each part alone.
- **Safe to change:** fewer surprises when one part changes.

### Designing with Composition

1. List the jobs: logging, address, contact, fuel.
2. Make one small type per job.
3. Build bigger types from them, embedded or named.
4. Use interfaces to treat different types the same way.

**Easy way to remember**

- "X **has a** Y" → put a Y inside X.
- Want Y's fields and methods on X directly → embed Y.
- Want different types treated the same → use an interface.

**Simple lesson:** Go builds types from parts (has-a) instead of family trees (is-a).

## TL;DR

1. **Composition** = build big types from small types inside them.
   - **Has-a** = "a Student has an Address" → a field.
2. **Named field** = `Home Address`, reached as `s.Home.City`.
3. **Embedding** = a type with no field name: `Person`.
   - **Promoted fields** = `t.Name` means `t.Person.Name`.
   - **Promoted methods** = `lib.Log()` means `lib.Logger.Log()`.
4. **Method resolution** = the outer type first, then embedded types.
   - Same name in two embedded types = ambiguous, use the full path.
5. **Embedding is not inheritance.** The embedded part does not know the outer type.
6. **Go prefers composition** = small parts, flexible, safe to change.

## Common mistakes

| Mistake | Wrong idea | Correct idea | What goes wrong |
|---|---|---|---|
| Expecting `Animal`'s method to call `Dog`'s method | Embedding is inheritance | The embedded part knows only itself | The base behaviour runs. |
| `s.Number` with two embedded `Number` fields | Go picks one | Go cannot choose | `ambiguous selector s.Number` |
| Filling an embedded struct as `Teacher{Name: "x"}` | Promoted fields work in literals | Use `Teacher{Person: Person{Name: "x"}}` | `unknown field Name in struct literal` |
| Naming the field when you want promotion | Any field is promoted | Only embedded (unnamed) fields are | `t.Name` is `undefined`. |
| A pointer method on an embedded value in a copy | The copy changes the original | Copies are separate | Changes are lost. |
| Building deep chains of embedding | More levels = more reuse | Keep it shallow | Hard to see where a field comes from. |

## Check Yourself

## Exercises

## What to Remember

- Composition builds big types from small parts (has-a).
- A named field is reached with its name: `s.Home.City`.
- An embedded field has no name. Its fields and methods are promoted.
- The outer type's own method always wins.
- Embedding is not inheritance. Go uses composition and interfaces instead.

Next: **Interfaces and Polymorphism**. You will learn how Go treats different types the same way, by what they can do.
