// types4.go
package main
import (
"fmt"
)
type Point struct {
x, y float64
}
// The method set of an interface is a the set of methods listed in it.
type Rectangler interface {
width() float64
height() float64
upperLeft() Point
} // Rectangler
//////////////////////////////////////////////////////////////////
// In the following methods, the parameter r is of interface type Rectangler,
// which means any object that implements Rectangler could be passed to it. A
// type T implements the Rectangler interface is the methods set of T is a
// superset of the method set of Rectangle. The functions can only use methods
// in the method set of r, i.e. only methods listed in Rectangler.
func print(r Rectangler) {
fmt.Printf("<corner=(%v, %v), w=%v, h=%v>",
r.upperLeft().x, r.upperLeft().y, r.width(), r.height())
}
func println(r Rectangler) {
print(r)
fmt.Println()
}
func area(r Rectangler) float64 {
return r.width() * r.height()
}
func perimeter(r Rectangler) float64 {
return 2 * (r.width() * r.height())
}
//////////////////////////////////////////////////////////////////
type Rect1 struct {
uLeft Point
lRight Point
} // Rect1
func makeRect1(x, y, width, height float64) Rect1 {
return Rect1{Point{x, y}, Point{x + width, y + height}}
}
// The method set of Rect1 is all the methods with Rect1 as a receiever, i.e.
// width, height, and upperLeft. The method set of *Rect1 is all the methods
// with *Rect1 or Rect1 as the receiver. There are no methods with *Rect1 as
// the receiver, so the method set of *Rect1 is the same as the method set for
// Rect1.
func (r Rect1) width() float64 {
return r.lRight.x - r.uLeft.x
}
func (r Rect1) height() float64 {
return r.lRight.y - r.uLeft.y
}
func (r Rect1) upperLeft() Point {
return r.uLeft
}
//////////////////////////////////////////////////////////////////
type Rect2 struct {
uLeft Point
w, h float64
} // Rect2
func makeRect2(x, y, width, height float64) Rect2 {
return Rect2{Point{x, y}, width, height}
}
func (r Rect2) width() float64 {
return r.w
}
func (r Rect2) height() float64 {
return r.h
}
func (r Rect2) upperLeft() Point {
return Point{r.uLeft.x + r.w, r.uLeft.y + r.h}
}
//////////////////////////////////////////////////////////////////
func main() {
a := makeRect1(0, 0, 10, 5)
b := makeRect2(0, 0, 2, 2)
println(a)
fmt.Printf("area=%v, perim=%v\n", area(a), perimeter(a))
println(b)
fmt.Printf("area=%v, perim=%v\n", area(b), perimeter(b))
} // main