Interfaces และการ Satisfy แบบ Implicit
Interfaces: เป็น structural แต่ implicit
หัวข้อที่มีชื่อว่า “Interfaces: เป็น structural แต่ implicit”TypeScript ใช้ structural typing — ถ้า type มีรูปร่างตรงตามที่ต้องการ ก็ใช้แทนกันได้เลย interface ของ Go ก็ทำงานแบบเดียวกัน แต่ต่างกันตรงจุดสำคัญหนึ่งอย่าง: คุณไม่ต้องเขียน implements เลย ถ้า type ไหนมี method ครบทุกตัวที่ interface ต้องการ type นั้นก็ satisfy interface โดยอัตโนมัติ เรียกว่า implicit satisfaction
การนิยามและการ satisfy interface
หัวข้อที่มีชื่อว่า “การนิยามและการ satisfy interface”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());}type Greeter interface { Greet() string}
type User struct { Name string }
// No "implements" — User satisfies Greeter automaticallyfunc (u User) Greet() string { return "Hello from " + u.Name}
func sayHello(g Greeter) { fmt.Println(g.Greet())}จุดแข็ง: แยกการนิยามออกจากการ implement
หัวข้อที่มีชื่อว่า “จุดแข็ง: แยกการนิยามออกจากการ implement”เพราะการ satisfy เป็นแบบ implicit เราจึงนิยาม interface ไว้ใน package ฝั่งที่ ใช้งาน ได้เลย ไม่ต้องไปนิยามใน package ที่ให้ implementation แปลว่าคนเขียน library ไม่จำเป็นต้องรู้จัก interface ของคุณเลย — ขอแค่ type ของเขามี method ครบ ก็ใช้ได้
// TypeScript — interface often lives with the classinterface Logger { log(msg: string): void;}class ConsoleLogger implements Logger { log(msg: string) { console.log(msg); }}// 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 Loggertype 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) }}Loading Go runtime (first run only, ~8 MB)…