Chapter 11 - Interfaces

Exercise 1: Interfaces

Here we have Cuboid and Sphere types, both of which have Volume and SurfaceArea methods. We also have a PrintInfo function that accepts a Cuboid, and calls Volume and SurfaceArea on it so it can print that info.

In the main function we pass a Cuboid to PrintInfo, which compiles fine. But then we try to pass a Sphere to PrintInfo as well, which results in a compile error. PrintInfo is only set up to accept Cuboid values, even though Sphere values have identical methods.

Let’s get the PrintInfo function to accept both Cuboid and Sphere values. Define a Solid interface consisting of Volume and SurfaceArea methods. Then modify PrintInfo to accept a parameter with a Solid interface type instead of Cuboid.

Solution

package main

import (
	"fmt"
	"math"
)

type Cuboid struct {
	width  float64
	length float64
	height float64
}

func (c Cuboid) Volume() float64 {
	return c.length * c.width * c.height
}

func (c Cuboid) SurfaceArea() float64 {
	area := 2 * c.length * c.width
	area += 2 * c.length * c.height
	area += 2 * c.height * c.width
	return area
}

type Sphere struct {
	radius float64
}

func (s Sphere) Volume() float64 {
	return (4.0 / 3.0) * math.Pi * math.Pow(s.radius, 3)
}

func (s Sphere) SurfaceArea() float64 {
	return 2 * math.Pi * math.Pow(s.radius, 2)
}

// YOUR CODE HERE: Define a Solid interface.
type Solid interface {
	Volume() float64
	SurfaceArea() float64
}

// YOUR CODE HERE: Revise PrintInfo to accept a parameter
// that satisfies the Solid interface.
func PrintInfo(s Solid) {
	fmt.Println(s)
	fmt.Println("Volume:", s.Volume())
	fmt.Println("Surface Area:", s.SurfaceArea())
}

func main() {
	c := Cuboid{length: 2.5, width: 5.0, height: 10.5}
	PrintInfo(c)
	s := Sphere{radius: 2.0}
	PrintInfo(s)
}

Output:

{5 2.5 10.5}
Volume: 131.250
Surface Area: 182.500
{2}
Volume: 33.510
Surface Area: 50.265