Interfaces

Interface adalah kumpulan method signatures yang dapat diimplementasikan oleh tipe data lain. Interface memungkinkan abstraksi dan polymorphism dalam Go.

Contoh Masalah

Bagaimana cara:

  1. Membuat abstraksi untuk berbagai tipe
  2. Menerapkan polymorphism
  3. Membuat code yang lebih fleksibel

Penyelesaian

package main

import (
    "fmt"
    "math"
)

// 1. Interface dasar
type Shape interface {
    Area() float64
    Perimeter() float64
}

// Implementasi untuk Rectangle
type Rectangle struct {
    Width  float64
    Height float64
}

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

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

// Implementasi untuk Circle
type Circle struct {
    Radius float64
}

func (c Circle) Area() float64 {
    return math.Pi * c.Radius * c.Radius
}

func (c Circle) Perimeter() float64 {
    return 2 * math.Pi * c.Radius
}

// 2. Interface untuk String representation
type Stringer interface {
    String() string
}

func (r Rectangle) String() string {
    return fmt.Sprintf("Rectangle(width: %.2f, height: %.2f)", 
        r.Width, r.Height)
}

func (c Circle) String() string {
    return fmt.Sprintf("Circle(radius: %.2f)", c.Radius)
}

// 3. Empty interface
func describe(i interface{}) {
    fmt.Printf("Type: %T, Value: %v\n", i, i)
}

// 4. Interface composition
type ShapeWithColor interface {
    Shape
    Color() string
}

// ColoredRectangle implements ShapeWithColor
type ColoredRectangle struct {
    Rectangle
    color string
}

func (cr ColoredRectangle) Color() string {
    return cr.color
}

// 5. Type assertion
func getArea(s Shape) float64 {
    // Type assertion untuk mendapatkan specific type
    if circle, ok := s.(Circle); ok {
        fmt.Printf("This is a circle with radius %.2f\n", 
            circle.Radius)
    }
    return s.Area()
}

// 6. Type switch
func classifyShape(s Shape) string {
    switch v := s.(type) {
    case Circle:
        return fmt.Sprintf("Circle with radius %.2f", v.Radius)
    case Rectangle:
        return fmt.Sprintf("Rectangle %v x %v", v.Width, v.Height)
    default:
        return "Unknown shape"
    }
}

func main() {
    // Contoh 1: Basic interface usage
    var shapes []Shape
    shapes = append(shapes, Rectangle{Width: 3, Height: 4})
    shapes = append(shapes, Circle{Radius: 5})

    fmt.Println("Calculating shape properties:")
    for _, shape := range shapes {
        fmt.Printf("Area: %.2f\n", shape.Area())
        fmt.Printf("Perimeter: %.2f\n", shape.Perimeter())
    }

    // Contoh 2: Stringer interface
    rect := Rectangle{Width: 2, Height: 3}
    circle := Circle{Radius: 4}
    
    fmt.Printf("\nString representations:\n")
    fmt.Println(rect.String())
    fmt.Println(circle.String())

    // Contoh 3: Empty interface
    fmt.Printf("\nEmpty interface examples:\n")
    describe(42)
    describe("Hello")
    describe(true)
    describe(Rectangle{Width: 2, Height: 5})

    // Contoh 4: Interface composition
    coloredRect := ColoredRectangle{
        Rectangle: Rectangle{Width: 3, Height: 4},
        color:     "blue",
    }
    
    fmt.Printf("\nColored shape:\n")
    fmt.Printf("Area: %.2f\n", coloredRect.Area())
    fmt.Printf("Color: %s\n", coloredRect.Color())

    // Contoh 5: Type assertion
    fmt.Printf("\nType assertion example:\n")
    getArea(circle)
    getArea(rect)

    // Contoh 6: Type switch
    fmt.Printf("\nType switch examples:\n")
    for _, shape := range shapes {
        fmt.Println(classifyShape(shape))
    }
}

Penjelasan Kode

  1. Interface Definition

    • Kumpulan method signatures
    • Implementasi implisit
    • Tidak perlu keyword implements
  2. Interface Types

    • Basic interface
    • Empty interface
    • Interface composition
  3. Type Assertions

    • Mengecek concrete type
    • Type switch
    • Safe type conversion

Output

Calculating shape properties:
Area: 12.00
Perimeter: 14.00
Area: 78.54
Perimeter: 31.42

String representations:
Rectangle(width: 2.00, height: 3.00)
Circle(radius: 4.00)

Empty interface examples:
Type: int, Value: 42
Type: string, Value: Hello
Type: bool, Value: true
Type: main.Rectangle, Value: {2 5}

Colored shape:
Area: 12.00
Color: blue

Type assertion example:
This is a circle with radius 5.00
Area: 78.54
Area: 6.00

Type switch examples:
Rectangle 3 x 4
Circle with radius 5.00

Tips

  • Buat interface yang kecil dan fokus
  • Gunakan composition untuk interface kompleks
  • Interface dideklarasikan oleh user, bukan implementor
  • Gunakan empty interface dengan hati-hati
  • Selalu handle type assertion dengan aman