# Interface

Interface adalah adalah kumpulan definisi method yang tidak memiliki isi (hanya definisi saja) yang dibungkus dengan nama tertentu.

Interface merupakan tipe data. Nilai objek bertipe interface zero value-nya adalah `nil`. Interface mulai bisa digunakan jika sudah ada isinya, yaitu objek konkret yang memiliki definisi method yang sama dengan yang ada di interface.

```go
type BangunDatar interface {
    luas() int
    keliling() int
}
```

#### Lalu yang menjadi pertanyaan, kenapa dan kapan menggunakan Interface?

Menulis kode yang fleksibel, dapat digunakan kembali, dan modular sangat penting dalam mengembangkan program. Ini juga adalah kenapa Go dibuat. Go sangat mendukung penulisan code yang clean, simple, reliable, dan efficient.&#x20;

Jadi Interface sebenarnya adalah tools yang bisa kita pakai atau tidak. Tetapi Interface dapat membuat kode menjadi clean, shorter, dan more readable.

### Mendefenisikan Behaviour

Sebelum masuk ke contoh Interface lebih detail, mari kita lihat studi kasus berikut:

```go
package main

import "fmt"

type Persegi struct {
	sisi float64
}

func (persegi Persegi) luas() float64 {
	return persegi.sisi * persegi.sisi
}

type PersegiPanjang struct {
	panjang float64
	lebar   float64
}

func (persegiPanjang PersegiPanjang) luas() float64 {
	return persegiPanjang.panjang * persegiPanjang.lebar
}

type Segitiga struct {
	alas   float64
	tinggi float64
}

func (segitiga Segitiga) luas() float64 {
	return 0.5 * (segitiga.alas * segitiga.tinggi)
}

func main() {
	p := Persegi{sisi: 5}
	luasPersegi := luasBangunDatar(p)
	fmt.Println(luasPersegi)

	pp := PersegiPanjang{panjang: 4, lebar: 6}
	luasPersegiPanjang := luasBangunDatar(pp)
	fmt.Println(luasPersegiPanjang)

	s := Segitiga{alas: 20, tinggi: 10}
	luasSegitiga := s.luas()
	fmt.Println(luasSegitiga)
}

```

Dari kode di atas tidak ada yang salah. Jika dijalankan hasilnya pun akan sesuai.

![Menampilkan masing-masing luas bangun datar](https://2969676661-files.gitbook.io/~/files/v0/b/gitbook-legacy-files/o/assets%2F-MQaVepPFjuLoNjbs6f8%2F-MScOcZCw9qteAZUh4Nq%2F-MScZ24S8co6kC1goWHc%2FScreen%20Shot%202021-02-03%20at%2022.43.21.png?alt=media\&token=f1ea6a44-dc25-4a26-9c85-1ede9f12d088)

Kita bisa lihat ada behaviour yang mirip diantara masing-masing `struct` yaitu sama-sama memiliki method `luas` . Untuk itu kita akan membuat `interface` untuk menampung method tersebut.

### Mendefenisikan Interface

Untuk membuat tipe data Interface kita membutuhkan keyword `type` dan `interface` . Kita akan membuat `interface` bernama `BangunDatar` :

```go
type BangunDatar interface {
    luas() float64
}
```

Lalu kita akan membuat function yang memiliki parameter dengan tipe data `interface` .

```go
func luasBangunDatar(b BangunDatar) float64 {
	return b.luas()
}
```

Kita akan coba menggabungkan kedua kode di atas dengan kode sebelumnya:

```go
package main

import "fmt"

type BangunDatar interface {
	luas() float64
}

type Persegi struct {
	sisi float64
}

func (persegi Persegi) luas() float64 {
	return persegi.sisi * persegi.sisi
}

type PersegiPanjang struct {
	panjang float64
	lebar   float64
}

func (persegiPanjang PersegiPanjang) luas() float64 {
	return persegiPanjang.panjang * persegiPanjang.lebar
}

type Segitiga struct {
	alas   float64
	tinggi float64
}

func (segitiga Segitiga) luas() float64 {
	return 0.5 * (segitiga.alas * segitiga.tinggi)
}

func main() {
	p := Persegi{sisi: 5}
	luasPersegi := luasBangunDatar(p)
	fmt.Println(luasPersegi)

	pp := PersegiPanjang{panjang: 4, lebar: 6}
	luasPersegiPanjang := luasBangunDatar(pp)
	fmt.Println(luasPersegiPanjang)

	s := Segitiga{alas: 20, tinggi: 10}
	luasSegitiga := s.luas()
	fmt.Println(luasSegitiga)
}

func luasBangunDatar(b BangunDatar) float64 {
	return b.luas()
}
```

Jadi fungsi `luasBangunDatar` tidak memperdulikan parameter nilai dari masing-masing bangun datar. Kita dapat menambahkan sebanyak mungkin bangun datar yang kita ingin hitung luasnya denga catatan `struct` harus memiliki method yang terdaftar pada `interface` dan memiliki isi sesuai dengan konteksnya masing-masing.

### Studi kasus #2

Perhatikan kode di bawah ini:

```go
package main

import "fmt"

type Article struct {
    Title  string
    Author string
}

func (a Article) String() string {
    return fmt.Sprintf("The %q article was written by %s.", a.Title, a.Author)
}

type Book struct {
    Title  string
    Author string
    Pages  int
}

func (b Book) String() string {
    return fmt.Sprintf("The %q book was written by %s.", b.Title, b.Author)
}

type Stringer interface {
    String() string
}

func main() {
    a := Article{
        Title:  "Understanding Interfaces in Go",
        Author: "Sammy Shark",
    }
    Print(a)

    b := Book{
        Title:  "All About Go",
        Author: "Jenny Dolphin",
        Pages:  25,
    }
    Print(b)
}

func Print(s Stringer) {
    fmt.Println(s.String())
}
```

![](https://2969676661-files.gitbook.io/~/files/v0/b/gitbook-legacy-files/o/assets%2F-MQaVepPFjuLoNjbs6f8%2F-MScOcZCw9qteAZUh4Nq%2F-MScbOnXxvcpRq_7sVJo%2FScreen%20Shot%202021-02-03%20at%2022.58.04.png?alt=media\&token=fdaefc40-0a6d-473f-9714-bd3b06918065)

Pada studi kasus di atas ada kesamaan behaviour yaitu kedua `struct` sama-sama memiliki method `String` untuk menampilkan teks informasi Buku dan Artikel.
