Class (2)

Encapsulation

คลาสใน JavaScript, TypeScript ก็รองรับการตั้งค่า Access เหมือนกับภาษาทั่วๆ ไป เพื่อใช้ซ่อนข้อมูลจากคลาสอื่นๆ ได้ คีย์เวิร์ดที่ใช้คือ public protected และ private

Public Access

การตั้งค่าของตัวแปรและเมธอดเป็น public จะมีผลให้สามารถเรียกใช้จากข้างนอกได้

class Dog {
public name: string // ใช้ได้ทั้งใน ​Class และเรียกจากนอก Class
public bark() {
console.log("Woof!")
}
}
const d = new Dog()
d.name = "Doge"
d.bark() // Woof!

ปกติถ้าไม่กำหนด Access ใดๆ เลย จะถือว่าเป็น public โดยอัตโนมัติ เราจึงไม่เห็นคนใช้ public กันเท่าไร

Protected Access

สำหรับ protected จะไม่สามารถเรียกจากภายนอกได้ แต่ถ้าเกิดการสร้าง Subclass ด้วยการใช้ extend จะสามารถใช้ภายใน Subclass ได้

class Dog {
protected color: string = "white" // color จะใช้ได้แค่ภายใน Class และ Subclass
printColor() {
console.log(`This dog is ${this.color}`)
}
}
class MyDog extends Dog {
printColor() {
console.log(`My dog is ${this.color}, and he's cute!`)
}
}
const d = new Dog()
d.color // ❌ เรียกใช้ไม่ได้ เพราะเป็น protected
d.printColor() // This dog is white
const e = new MyDog()
e.printColor() // My dog is white, and he's cute!

Private Access

ถ้าเป็น private ตัวแปรและเมธอดจะใช้ได้แค่ภายในคลาสนั้นเท่านั้น Subclass ก็ไม่สามารถใช้ได้

class Brain {
private cellCount: number // cellCount จะใช้ได้แค่ใน Class นี้
constructor(c: number) {
this.cellCount = c
}
countCells() {
console.log(`The brain has ${this.cellCount} cells`) // ✅
}
}
const brain = new Brain(84000)
console.log(brain.cellCount) // ❌ ไม่สามารถเรียกใช้ cellCount จากภายนอกคลาสได้
class BigBrain extends Brain {
doubleCells() {
// ❌ ไม่สามารถเรียกใช้ cellCount จาก Subclass ได้
this.cellCount = this.cellCount * 2
}
}

Static Members

การตั้งตัวแปรและเมธอดให้เป็น static จะทำให้สามารถเรียกใช้ได้จากคลาสนั้นโดยตรง โดยไม่ต้องสร้าง Object ด้วย new ก่อน วิธีนี้เหมาะกับการสร้างค่าคงที่หรือเมธอดที่ไม่ต้องใช้ค่าใน Object

class Tweet {
static charLimit = 280
message: string
static charLimitMessage() {
return `Character limit is ${Tweet.charLimit}` // เรียกใช้จากในคลาส
}
constructor(message: string) {
if (message.length > Tweet.charLimit) { // เรียกใช้จาก Constructor
throw new Error(Tweet.charLimitMessage())
}
this.message = message
}
}
Tweet.charLimit // เรียกใช้จากภายนอกคลาส

Generic Classes

เช่นเดียวกับ Interface เราสามารถใช้ Generic กับคลาสได้ ข้อแตกต่างคือการทำเป็นคลาสเราจะ Infer Type ด้วย Constructor Method ได้เลย

// เขียนแบบ Class
class Package<T> {
contents: T
constructor(value: T) { // Infer จาก value ที่นำเข้ามา
this.contents = value
}
}
const pkgObject = new Package("มันคือแป้ง") // T เป็น string จากการ Infer
// เขียนแบบ Interface
interface Package<T> {
contents: T
}
const pkgInterface: Package<string> = { contents: "มันคือแป้ง" } // ต้องกำหนด T เอง

เรื่องของคลาสยังมีอีกเยอะ แต่ขอไปศืกษาเพิ่มก่อนนะ (เนื้อหาเรื่องคลาสทั้งสองตอนครอบคลุมการใช้งานและการอ่านโค้ดของคนอื่นได้พอประมาณ ถ้าต้องการดูเนื้อหาท้ังหมดสามารถดูได้จาก TypeScript Handbook)