インターフェースとは
RubyやPythonには明示的に登場する概念ではないため、この場で確認しておきます。
Goにおけるインターフェースとは、メソッドの集合体のこと。他の言語では抽象クラスと呼ばれることもある概念です。
インターフェースの例
type Shape interface {
Area() float64 // 面積
Perimeter() float64 // 周囲
}
Shape
というインターフェースはArea()
とPerimeter()
という浮動小数点を返すメソッドを持っています。
このインターフェースはメソッドの詳細を知りません。
次に、このインターフェースを実装したRectangle
という構造体を定義します。
type Rectangle struct {
Width, Height float64
}
func (r Rectangle) Area() float64 {
return r.Width * r.Height
}
func (
r Rectangle) Perimeter() float64 {
return 2 * (r.Width + r.Height)
}
Rectangle
はArea()
とPerimeter()
を持っているため、インターフェースを満たしています。
もう一つCircle
を定義してみます。
type Circle struct {
radius float64
}
func (c Circle) Area() float64 {
return 3.14 * c.radius * c.radius
}
func (c Circle) Perimeter() float64 {
return 2 * 3.14 * c.radius
}
呼出部分です。
func main() {
var s Shape
s = Rectangle{width: 10, height: 20}
fmt.Println(s.Area())
fmt.Println(s.Perimeter())
s = Circle{radius: 10}
fmt.Println(s.Area())
fmt.Println(s.Perimeter())
}
これの何が嬉しいのか
例えばPrintAreaAndPerimeter()
のような関数を定義してみましょう。
引数にはインターフェースを受け取ります。
func PrintAreaAndPerimeter(s Shape) {
fmt.Println(s.Area())
fmt.Println(s.Perimeter())
}
先程の呼出部分を修正します。
func main() {
var r Shape
var c Shape
r = Rectangle{width: 10, height: 20}
c = Circle{radius: 10}
PrintAreaAndPerimeter(r)
PrintAreaAndPerimeter(c)
}
このようにすることで、新たに構造体Triangle
を定義するときでも、既存部分を修正する必要なく追加することが可能になります。