Interfaces and Embedding

An interface = type that specifies a set of method signatures. When a concrete type provides definitions for all the methods in an interface, it is said to implement the interface.

type Shape interface {
  Area() float64
  Perimeter() float64
}

func (r Rectangle) Area() float64 {
  return r.Length * r.Width
}

func (r Rectangle) Perimeter() float64 {
  return 2 * (r.Length + r.Width)
}

type Rectangle struct {
  Length, Width float64
}

func main() {
  var r Shape = Rectangle{Length: 3, Width: 4}
  fmt.Printf("Type of r: %T, Area: %v, Perimeter: %v.", r, r.Area(), r.Perimeter())
}

Embedding - allows one struct type to include another struct, inheriting the fields and methods of the embedded type. It is Go's mechanism to achieve composition over traditional inheritance.

type Address struct {
    Street, City, State string
}

type Person struct {
    Name string
    Address
}

p := Person{
    Name:    "Alice",
    Address: Address{"123 Main St", "Anytown", "CA"},
}
fmt.Println(p.Street)  // Output: 123 Main St

Embedding provides a way to "inherit" methods.

But it's not inheritance because Go doesn't have the keyword this, also we can't override the embedded's method implementation.

Type embedding isn't inheritance, and pretending it is will lead to bugs.

public class Animals {
  public static void main(String[] args) {
    Animals example = new Animals();
    example.Run();
  }
	
  public void Run() {
    Animal a = new Tiger();
    a.Greet();
  }
	
  interface Animal {
    public void Speak();
    public void Greet();
  }

  class Cat implements Animal {
    public void Speak() {
      System.out.println("meow");
    }

    public void Greet() {
      this.Speak();
      System.out.println("I'm a kind of cat!");
    }
  }

  class Tiger extends Cat {
    public void Speak() {
      System.out.println("roar");
    }
  }
}
roar
I'm a kind of cat!

In Java, this is a special implicit pointer that always has the runtime type of the class the method was originally invoked on. So Tiger.Greet() dispatches to Cat.Greet(), but the latter has a this pointer of type Tiger, and so this.Speak() dispatches to Tiger.Speak().

Resources:

Last updated