ข้ามไปยังเนื้อหา

Interfaces และการ Satisfy แบบ Implicit

TypeScript ใช้ structural typing — ถ้า type มีรูปร่างตรงตามที่ต้องการ ก็ใช้แทนกันได้เลย interface ของ Go ก็ทำงานแบบเดียวกัน แต่ต่างกันตรงจุดสำคัญหนึ่งอย่าง: คุณไม่ต้องเขียน implements เลย ถ้า type ไหนมี method ครบทุกตัวที่ interface ต้องการ type นั้นก็ satisfy interface โดยอัตโนมัติ เรียกว่า implicit satisfaction

TypeScript
interface Greeter {
greet(): string;
}
// TypeScript: no implements needed (structural)
class User {
constructor(public name: string) {}
greet(): string { return `Hello from ${this.name}`; }
}
function sayHello(g: Greeter) {
console.log(g.greet());
}
Go
type Greeter interface {
Greet() string
}
type User struct { Name string }
// No "implements" — User satisfies Greeter automatically
func (u User) Greet() string {
return "Hello from " + u.Name
}
func sayHello(g Greeter) {
fmt.Println(g.Greet())
}

เพราะการ satisfy เป็นแบบ implicit เราจึงนิยาม interface ไว้ใน package ฝั่งที่ ใช้งาน ได้เลย ไม่ต้องไปนิยามใน package ที่ให้ implementation แปลว่าคนเขียน library ไม่จำเป็นต้องรู้จัก interface ของคุณเลย — ขอแค่ type ของเขามี method ครบ ก็ใช้ได้

TypeScript
// TypeScript — interface often lives with the class
interface Logger {
log(msg: string): void;
}
class ConsoleLogger implements Logger {
log(msg: string) { console.log(msg); }
}
Go
// Go — interface lives with the consumer
// (in the package that needs it, not the one that provides it)
type Logger interface {
Log(msg string)
}
// This type in another package doesn't know about Logger
type ConsoleLogger struct{}
func (c ConsoleLogger) Log(msg string) { fmt.Println(msg) }
// ConsoleLogger satisfies Logger without knowing Logger exists
package main
import (
"fmt"
"math"
)
type Shape interface {
Area() float64
Perimeter() float64
}
type Circle struct{ Radius float64 }
type Rect struct{ Width, Height float64 }
func (c Circle) Area() float64 { return math.Pi * c.Radius * c.Radius }
func (c Circle) Perimeter() float64 { return 2 * math.Pi * c.Radius }
func (r Rect) Area() float64 { return r.Width * r.Height }
func (r Rect) Perimeter() float64 { return 2 * (r.Width + r.Height) }
func describe(s Shape) {
fmt.Printf("Area: %.2f, Perimeter: %.2f\n", s.Area(), s.Perimeter())
}
func main() {
shapes := []Shape{
Circle{Radius: 5},
Rect{Width: 4, Height: 3},
}
for _, s := range shapes {
describe(s)
}
}
type ใน Go บอกได้อย่างไรว่า implement interface แล้ว?
ที่ไหนคือที่ที่ idiomatic ในการนิยาม interface ของ Go?
structural typing ของ TypeScript กับการ satisfy interface แบบ implicit ของ Go นั้น:
empty interface ใน Go คืออะไร (type ที่ทุก type satisfy ได้)?