package main

import "fmt"

// section: types
// This example demonstrates the "shallowest depth" rule from the Go spec.
// When a field or method exists at multiple embedding depths, the
// shallowest one wins.

type Inner struct {
	Value string
}

func (i Inner) Describe() string {
	return "Inner: " + i.Value
}

type Middle struct {
	Inner // depth 2 from Outer
	Value string
}

func (m Middle) Describe() string {
	return "Middle: " + m.Value
}

type Outer struct {
	Middle // Middle.Describe is at depth 1
	Inner  // Inner.Describe is also at depth 1 - AMBIGUOUS!
}

// section: types

// section: fixed
// To fix ambiguity, define the method at depth 0 (on Outer itself)
type OuterFixed struct {
	Middle
	Inner
}

func (o OuterFixed) Describe() string {
	return fmt.Sprintf("Outer combining: %s and %s",
		o.Middle.Describe(), o.Inner.Describe())
}

// section: fixed

// section: main
func main() {
	// Shallowest depth wins - Middle.Value shadows Inner.Value
	m := Middle{
		Inner: Inner{Value: "inner-value"},
		Value: "middle-value",
	}
	fmt.Println("Middle.Value:", m.Value)       // "middle-value" (depth 0)
	fmt.Println("Middle.Inner.Value:", m.Inner.Value) // "inner-value" (explicit)

	// When depths are equal, both get evicted (ambiguous)
	// Uncommenting this would cause: "ambiguous selector o.Describe"
	// o := Outer{}
	// o.Describe()

	// Fixed version: depth 0 wins over depth 1
	of := OuterFixed{
		Middle: Middle{Value: "mid"},
		Inner:  Inner{Value: "in"},
	}
	fmt.Println("OuterFixed.Describe():", of.Describe())
}

// section: main
