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
.
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.
// YOUR CODE HERE: Revise PrintInfo to accept a parameter
// that satisfies the Solid interface.
func PrintInfo(c Cuboid) {
fmt.Println(c)
fmt.Printf("Volume: %0.3f\n", c.Volume())
fmt.Printf("Surface Area: %0.3f\n", c.SurfaceArea())
}
func main() {
c := Cuboid{length: 2.5, width: 5.0, height: 10.5}
PrintInfo(c)
s := Sphere{radius: 2.0}
PrintInfo(s)
}
Compile Error:
./prog.go:47:11: cannot use s (type Sphere) as type Cuboid in argument to PrintInfo
When you’re ready, have a look at our solution.
Exercise 2: Type Assertions
Here are updated Fan
and CoffeePot
types, both of which satisfy an Appliance
interface. We’ve also added a Use
method that accepts an Appliance
. Currently, Use
only calls the TurnOn
method on the Appliance
…
Update Use
so that it calls Oscillate
on the Appliance
if (and only if) it’s a Fan
. Use
should also call Brew
on the Appliance
if (and only if) it’s a CoffeePot
.
package main
import "fmt"
type Appliance interface {
TurnOn()
}
type Fan string
func (f Fan) TurnOn() {
fmt.Println("Spinning")
}
func (f Fan) Oscillate() {
fmt.Println("Rotating on base")
}
type CoffeePot string
func (c CoffeePot) TurnOn() {
fmt.Println("Powering up")
}
func (c CoffeePot) Brew() {
fmt.Println("Heating Up")
}
func Use(appliance Appliance) {
fmt.Println(appliance)
appliance.TurnOn()
// YOUR CODE HERE: If the appliance is a
// Fan, call its Oscillate method.
// If the appliance is a CoffeePot, call
// its Brew method.
}
func main() {
Use(Fan("Windco Breeze"))
Use(CoffeePot("LuxBrew"))
}
Desired Output:
Windco Breeze
Spinning
Rotating on base
LuxBrew
Powering up
Heating Up
Here’s our solution.