Interface
Di bahasa Go, interface adalah tipe abstrak yang digunakan untuk mendefinisikan sekumpulan signature metode tanpa menyediakan implementasi metode. Filosofi inti interface adalah mendeskripsikan perilaku, sedangkan implementasi perilaku spesifik disediakan oleh tipe yang mengimplementasikan interface. Interface di bahasa Go banyak digunakan untuk mencapai polimorfisme, loose coupling, dan reuse kode.
Konsep
Sejarah perkembangan Go tentang interface memiliki分水岭, di Go1.17 dan sebelumnya,官方 di reference manual untuk definisi interface adalah: sekumpulan metode.
An interface type specifies a method set called its interface.
Definisi implementasi interface adalah
A variable of interface type can store a value of any type with a method set that is any superset of the interface. Such a type is said to implement the interface
Diterjemahkan adalah, ketika method set sebuah tipe adalah superset dari method set interface, dan nilai tipe tersebut dapat disimpan oleh variabel tipe interface ini, maka disebut tipe ini mengimplementasikan interface ini.
Namun di Go1.18, definisi interface发生了变化, interface didefinisikan sebagai: sekumpulan tipe.
An interface type defines a type set.
Definisi implementasi interface adalah
A variable of interface type can store a value of any type that is in the type set of the interface. Such a type is said to implement the interface
Diterjemahkan adalah, ketika sebuah tipe berada di dalam type set sebuah interface, dan nilai tipe tersebut dapat disimpan oleh variabel tipe interface ini, maka disebut tipe ini mengimplementasikan interface ini. Dan memberikan definisi tambahan sebagai berikut.
Kapan dapat disebut tipe T mengimplementasikan interface I
- T bukan interface, dan merupakan elemen di type set interface I
- T adalah interface, dan type set T adalah subset dari type set interface I
Jika T mengimplementasikan sebuah interface, maka nilai T juga mengimplementasikan interface ini.
Perubahan terbesar Go di 1.18 adalah menambahkan generik, definisi interface baru adalah untuk melayani generik, tetapi sama sekali tidak mempengaruhi penggunaan interface sebelumnya, sekaligus interface juga dibagi menjadi dua kategori,
- Basic Interface: Interface yang hanya berisi method set adalah basic interface
- General Interface: Interface yang berisi type set adalah general interface
Apa itu method set, method set adalah sekumpulan metode, sama juga, type set adalah sekumpulan tipe.
TIP
Anda mungkin merasa konsep ini sangat sulit dipahami, tetapi sebenarnya Anda sama sekali tidak perlu memahami semua hal di atas.
Basic Interface
Di depan telah dibahas basic interface adalah method set, adalah sekumpulan metode.
Deklarasi
Pertama lihat seperti apa interface.
type Person interface {
Say(string) string
Walk(int)
}Ini adalah interface Person, memiliki dua metode yang diekspos ke luar Walk dan Say, di interface, nama parameter fungsi menjadi tidak penting, tentu jika ingin menambahkan nama parameter dan nama nilai return juga diizinkan.
Inisialisasi
Hanya interface tidak dapat diinisialisasi, karena ia hanya sekumpulan spesifikasi, tidak memiliki implementasi spesifik, tetapi dapat dideklarasikan.
func main() {
var person Person
fmt.Println(person)
}Output
<nil>Implementasi
Pertama lihat contoh, sebuah perusahaan konstruksi menginginkan crane dengan spesifikasi khusus, oleh karena itu memberikan spesifikasi dan gambar crane khusus, dan menunjukkan crane harus memiliki fungsi mengangkat dan menggantung barang, perusahaan konstruksi tidak bertanggung jawab membuat crane, hanya memberikan spesifikasi, ini disebut interface, oleh karena itu perusahaan A menerima pesanan, membuat crane terbaik di dunia sesuai teknologi eksklusif perusahaan sendiri dan menyerahkannya kepada perusahaan konstruksi, perusahaan konstruksi tidak peduli menggunakan teknologi apa untuk implementasi, juga tidak peduli crane terbaik di dunia, hanya perlu dapat mengangkat dan menggantung barang sudah cukup, menyediakan fungsi spesifik sesuai spesifikasi interface, ini disebut implementasi. Hanya menggunakan fungsi sesuai spesifikasi interface, mengabaikan implementasi internalnya, ini disebut pemrograman berorientasi interface. Setelah beberapa waktu, crane terbaik di dunia rusak, perusahaan A juga kabur, oleh karena itu perusahaan B membuat crane raksasa yang lebih hebat sesuai spesifikasi, karena sama memiliki fungsi mengangkat dan menggantung barang, dapat seamlessly terhubung dengan crane terbaik di dunia, tidak mempengaruhi进度 konstruksi, konstruksi berhasil diselesaikan, implementasi internal berubah tetapi fungsi tidak berubah, tidak mempengaruhi penggunaan sebelumnya, dapat diganti sesuka hati, ini adalah keuntungan pemrograman berorientasi interface.
Selanjutnya akan mendeskripsikan situasi di atas menggunakan Go
// Interface Crane
type Crane interface {
JackUp() string
Hoist() string
}
// Crane A
type CraneA struct {
work int // field internal berbeda mewakili detail internal berbeda
}
func (c CraneA) Work() {
fmt.Println("Menggunakan teknologi A")
}
func (c CraneA) JackUp() string {
c.Work()
return "jackup"
}
func (c CraneA) Hoist() string {
c.Work()
return "hoist"
}
// Crane B
type CraneB struct {
boot string
}
func (c CraneB) Boot() {
fmt.Println("Menggunakan teknologi B")
}
func (c CraneB) JackUp() string {
c.Boot()
return "jackup"
}
func (c CraneB) Hoist() string {
c.Boot()
return "hoist"
}
type ConstructionCompany struct {
Crane Crane // Hanya menyimpan crane sesuai tipe Crane
}
func (c *ConstructionCompany) Build() {
fmt.Println(c.Crane.JackUp())
fmt.Println(c.Crane.Hoist())
fmt.Println("Konstruksi selesai")
}
func main() {
// Menggunakan Crane A
company := ConstructionCompany{CraneA{}}
company.Build()
fmt.Println()
// Ganti Crane B
company.Crane = CraneB{}
company.Build()
}Output
Menggunakan teknologi A
jackup
Menggunakan teknologi A
hoist
Konstruksi selesai
Menggunakan teknologi B
jackup
Menggunakan teknologi B
hoist
Konstruksi selesaiDi contoh di atas, dapat mengamati implementasi interface adalah implisit, juga sesuai dengan definisi官方 untuk implementasi basic interface: method set adalah superset dari method set interface, oleh karena itu di Go, mengimplementasikan interface tidak perlu keyword implements untuk secara eksplisit menentukan akan mengimplementasikan interface mana, hanya perlu mengimplementasikan semua metode interface, itu adalah mengimplementasikan interface tersebut. Setelah memiliki implementasi, dapat menginisialisasi interface, struct perusahaan konstruksi mendeklarasikan variabel member tipe Crane di dalamnya, dapat menyimpan semua nilai yang mengimplementasikan interface Crane, karena adalah variabel tipe Crane, oleh karena itu metode yang dapat diakses hanya JackUp dan Hoist, metode internal lainnya seperti Work dan Boot tidak dapat diakses.
Sebelumnya telah disebutkan bahwa setiap tipe custom dapat memiliki metode, maka sesuai definisi implementasi, setiap tipe custom dapat mengimplementasikan interface, berikut beberapa contoh khusus.
type Person interface {
Say(string) string
Walk(int)
}
type Man interface {
Exercise()
Person
}Method set interface Man adalah superset dari Person, oleh karena itu Man juga mengimplementasikan interface Person, tetapi ini lebih mirip "inheritance".
type Number int
func (n Number) Say(s string) string {
return "bibibibibi"
}
func (n Number) Walk(i int) {
fmt.Println("can not walk")
}Tipe dasar Number adalah int, meskipun ini terlihat sangat mengejutkan di bahasa lain, tetapi method set Number memang superset dari Person, oleh karena itu juga算 implementasi.
type Func func()
func (f Func) Say(s string) string {
f()
return "bibibibibi"
}
func (f Func) Walk(i int) {
f()
fmt.Println("can not walk")
}
func main() {
var function Func
function = func() {
fmt.Println("do somthing")
}
function()
}Sama juga, tipe fungsi juga dapat mengimplementasikan interface.
Empty Interface
type Any interface{
}Interface Any tidak memiliki method set, sesuai definisi implementasi, semua tipe adalah implementasi interface Any, karena method set semua tipe adalah superset dari empty set, oleh karena itu interface Any dapat menyimpan nilai tipe apapun.
func main() {
var anything Any
anything = 1
println(anything)
fmt.Println(anything)
anything = "something"
println(anything)
fmt.Println(anything)
anything = complex(1, 2)
println(anything)
fmt.Println(anything)
anything = 1.2
println(anything)
fmt.Println(anything)
anything = []int{}
println(anything)
fmt.Println(anything)
anything = map[string]int{}
println(anything)
fmt.Println(anything)
}Output
(0xe63580,0xeb8b08)
1
(0xe63d80,0xeb8c48)
something
(0xe62ac0,0xeb8c58)
(1+2i)
(0xe62e00,0xeb8b00)
1.2
(0xe61a00,0xc0000080d8)
[]
(0xe69720,0xc00007a7b0)
map[]Melalui output akan menemukan, hasil dua output tidak konsisten, sebenarnya interface internal dapat dianggap sebagai tuple yang terdiri dari (val,type), type adalah tipe spesifik, saat memanggil metode akan memanggil nilai spesifik dari tipe spesifik.
interface{}Ini juga empty interface, tetapi adalah anonymous interface, saat pengembangan biasanya akan menggunakan anonymous interface untuk表示 menerima nilai tipe apapun, contoh sebagai berikut
func main() {
DoSomething(map[int]string{})
}
func DoSomething(anything interface{}) interface{} {
return anything
}Di update selanjutnya,官方 mengajukan solusi lain, untuk kemudahan, dapat menggunakan any untuk menggantikan interace{}, keduanya sepenuhnya ekuivalen, karena yang pertama hanya alias tipe, sebagai berikut
type any = interface{}Saat membandingkan empty interface, akan membandingkan tipe dasarnya, jika tipe tidak cocok maka false, baru kemudian perbandingan nilai, misalnya
func main() {
var a interface{}
var b interface{}
a = 1
b = "1"
fmt.Println(a == b)
a = 1
b = 1
fmt.Println(a == b)
}Output adalah
false
trueJika tipe dasarnya tidak dapat dibandingkan, maka akan panic, untuk Go, apakah tipe data built-in dapat dibandingkan situasi sebagai berikut
| Tipe | Dapat Dibandingkan | Dasar |
|---|---|---|
| Tipe Numerik | Ya | Apakah nilai sama |
| Tipe String | Ya | Apakah nilai sama |
| Tipe Array | Ya | Apakah semua elemen array sama |
| Tipe Slice | Tidak | Tidak dapat dibandingkan |
| Struct | Ya | Apakah semua field value sama |
| Tipe Map | Tidak | Tidak dapat dibandingkan |
| Channel | Ya | Apakah alamat sama |
| Pointer | Ya | Apakah alamat yang disimpan pointer sama |
| Interface | Ya | Apakah data yang disimpan di dasar sama |
Di Go ada tipe interface khusus untuk mewakili semua tipe yang dapat dibandingkan, yaitu comparable
type comparable interface{ comparable }TIP
Jika mencoba membandingkan tipe yang tidak dapat dibandingkan, maka akan panic
General Interface
General interface adalah untuk melayani generik, hanya perlu menguasai generik, akan menguasai general interface, silakan前往 Generik
