บทความนี้เกี่ยวกับแนวคิดของ class และ object instances ในภาษา Kotlin อธิบายให้เข้าใจง่าย ๆ ด้วยการนึกภาพถึงการทอยลูกเต๋า แทนที่จะทอยลูกเต๋าจริง ๆ เราสามารถเขียนโปรแกรมที่จำลองการทอยลูกเต๋าได้ เราจะทดลองสร้างแอปทอยลูกเต๋า (Dice Roller app) เป็น Android แอปที่ผู้ใช้สามารถคลิกปุ่มในแอปเพื่อทอยลูกเต๋าได้ มาเริ่มกันเลย!

แต่ละครั้งที่เราทอยลูกเต๋า สำหรับลูกเต๋า 6 เหลี่ยมปกติ ผลลัพธ์อาจเป็นตัวเลขใดก็ได้ภายในช่วงของค่าที่เป็นไปได้ คือ 1, 2, 3, 4, 5 และ 6 เราต้องมีวิธีที่จะแสดงค่าทั้งหมดนี้อย่างถูกต้อง
เราสามารถใช้ฟังก์ชันที่เรียกว่า random () เพื่อสร้างและส่งคืนตัวเลขสุ่มสำหรับช่วงที่กำหนดได้
val randomNumber = (1..6).random()
เรากำลังเรียก random () บนช่วง 1..6 โดยใช้จุดระหว่างช่วงและการเรียกฟังก์ชัน สามารถอ่านได้ว่า “สร้างตัวเลขสุ่มจากช่วง 1..6” จากนั้นผลลัพธ์จะถูกเก็บไว้ในตัวแปร randomNumber
1..6 เป็นช่วงของ Kotlin เนื่องจากมีตัวเลขเริ่มต้น, จุดสองจุด, ตามด้วยตัวเลขสิ้นสุด (ไม่มีช่องว่าง) ช่วงสามารถอยู่ระหว่างจำนวนเต็มใดก็ได้ เช่น 3..46, 0..270, -6 .. + 6, -10 ..- 4
val rollButton: Button = findViewById(R.id.button)
rollButton.setOnClickListener {
// A 6-sided dice and roll it
val randomNumber = (1..6).random()
// Update the screen with the dice roll
val resultTextView: TextView = findViewById(R.id.textView)
resultTextView.text = randomNumber.toString()
}
แม้ว่าโค้ดที่เราเพิ่งเขียนจะใช้งานได้ดี แต่ก็ยากที่จะจินตนาการได้ว่ามันเกี่ยวกับลูกเต๋าจริง ๆ การจัดโปรแกรมให้เหมือนกับสิ่งที่มันเป็นตัวแทนมากขึ้นทำให้เข้าใจง่ายขึ้น
ลูกเต๋าทุกลูกทำงานเหมือนกัน มีคุณสมบัติเหมือนกัน เช่น มีด้านต่าง ๆ และมีพฤติกรรมเหมือนกัน เช่น หมุนได้ ใน Kotlin เราสามารถสร้างพิมพ์เขียวการเขียนโปรแกรมของลูกเต๋าที่ระบุว่าลูกเต๋ามีด้านต่าง ๆ และสามารถหมุนตัวเลขสุ่มได้ พิมพ์เขียวนี้เรียกว่า class
จาก class ดังกล่าว เราสามารถสร้างวัตถุที่เป็นลูกเต๋าจริง ๆ ได้ เรียกว่า object instances ยกตัวอย่างเช่น เราสามารถสร้างลูกเต๋าที่มี 4 ด้านหรือ 12 ด้านได้
Class คล้ายกับพิมพ์เขียวของสถาปนิก ไม่ใช่บ้านเป็นคำแนะนำในการสร้างบ้าน บ้านคือสิ่งที่เกิดขึ้นจริง หรือ object instance ที่ถูกสร้างขึ้นตามพิมพ์เขียว
การจัดทุกอย่างที่เกี่ยวกับลูกเต๋าไว้ใน class เรียกว่า encapsulation, encapsulation เป็นคำในจินตนาการที่ใหญ่มาก แต่โดยรวมมันมายถึงเราสามารถรวมฟังก์ชันการทำงานที่เกี่ยวข้องกันอย่างมีเหตุผลไว้ในที่เดียวได้
ตอนนี้เรามาสร้าง class และ object instance กัน
สร้าง class ใหม่ที่เรียกว่า Dice เพื่อแทนลูกเต๋าที่หมุนได้
class Dice {}
ภายใน class เราสามารถระบุคุณสมบัติต่าง ๆ สำหรับ class โดยใช้ตัวแปร ลูกเต๋าจริงสามารถมีจำนวนด้าน, สี, หรือน้ำหนัก แต่ในตอนนี้เราจะสนใจที่จำนวนด้านของลูกเต๋า สำหรับจำนวนด้านที่ลูกเต๋าของเราจะมีตอนนี้คือ 6 ด้าน
var numSide = 6
การทอยลูกเต๋าเป็นการกระทำที่สามารถนำไปใช้เป็นฟังก์ชันได้ และเนื่องจากลูกเต๋าทุกลูกสามารถทอยได้เราจึงสามารถเพิ่มฟังก์ชันสำหรับทอยลูกเต๋าใน Dice class ได้ เมื่อเราทอยลูกเต๋าฟังก์ชันนี้จะสร้างตัวเลขสุ่มระหว่าง 1 ถึงจำนวนด้านที่เรากำหนด
แทนที่เราจะแสดงตัวเลขที่สุ่มได้ในฟังก์ชัน การส่งคืนผลลัพธ์ของฟังก์ชันมีประโยชน์มากกว่ากับสิ่งที่เรียกว่าฟังก์ชัน ดังนั้นเราต้องระบุชนิดข้อมูลสำหรับข้อมูลที่ฟังก์ชันจะส่งคืน ในกรณีนี้ตัวเลขสุ่มคือ Int ให้ระบุไว้ต่อจากชื่อของฟังก์ชัน หลังวงเล็บให้เพิ่ม : เว้นวรรคแล้วตามด้วยประเภทของข้อมูลที่ส่งคืน และส่งคืนค่าจากฟังก์ชันโดยใช้คำสั่ง return
fun roll(): Int { return (1..numSide).random() }
class Dice {
var numSide = 6
fun roll(): Int {
return (1..numSide).random()
}
}
ด้วย Dice class นี้ เราจะมีพิมพ์เขียวของสิ่งที่เป็นลูกเต๋า เพื่อให้มีลูกเต๋าที่แท้จริงในโปรแกรมของเรา เราต้องสร้าง object instance ของ Dice และถ้าเราต้องการมีลูกเต๋า 3 ลูก เราจะต้องสร้าง object instance 3 ครั้ง myFirstDice, mySecondDice, myThirdDice
val myFirstDice = Dice()
สังเกตวงเล็บหลังชื่อ class ซึ่งแสดงว่าเรากำลังสร้าง object instance ใหม่จากคลาส
ตอนนี้เรามี myFirstDice เป็น object ที่สร้างจากพิมพ์เขียวซึ่งเราสามารถเข้าถึงคุณสมบัติของมันได้ คุณสมบัติเดียวของลูกเต๋าที่มีใน class ตอนนี้คือจำนวนด้าน และเราเปลี่ยนจำนวนด้านให้ลูกเต๋าของเรามี 12 ด้าน เพราะลูกเต๋าไม่จำเป็นต้องมีแค่ 6 ด้าน มันสามารถมีรูปทรงและขนาดได้ตั้งแต่ 4 ด้าน 8 ด้าน สูงสุดคือ 120 ด้าน!
myFirstDice.numSide = 12
เราทอยลูกเต๋าที่เราสร้าง โดยเรียกฟังก์ชัน roll () บน myFirstDice
val diceRoll = myFirstDice.roll()
fun rollDice() {
val myFirstDice = Dice()
myFirstDice.numSide = 12
val diceRoll = myFirstDice.roll()
val resultTextView: TextView = findViewById(R.id.textView)
resultTextView.text = diceRoll.toString()
}
ตอนนี้เรามีพิมพ์เขียวของลูกเต๋า (Dice class) และมีลูกเต๋าจริงที่มี 12 ด้าน (myFirstDice)
แนวคิดของ class คือการเป็นตัวแทนของสิ่งหนึ่งซึ่งมักเป็นสิ่งที่มีอยู่จริงในโลกแห่งความเป็นจริง ซึ่งในกรณีนี้ Dice class เป็นตัวแทนของลูกเต๋าที่มีอยู่จริง ในโลกแห่งความเป็นจริงลูกเต๋าลูกหนึ่งไม่สามารถเปลี่ยนจำนวนด้านได้ หากเราต้องการจำนวนด้านที่แตกต่างกันเราต้องสร้างลูกเต๋าที่แตกต่างกัน โดยทางโปรแกรมหมายความว่าแทนที่จะเปลี่ยนคุณสมบัติจำนวนด้านของ object instance ของ Dice ที่มีอยู่ เราควรสร้าง object instance ของลูกเต๋าใหม่พร้อมจำนวนด้านที่เราต้องการ
มาปรับปรุง class และการสร้าง object instance ของเรากัน
แก้ไข Dice class เพื่อให้สามารถระบุจำนวนด้านได้เมื่อเราสร้าง object instance ใหม่
class Dice (val numSide: Int) {}
สร้าง object instance ของ Dice พร้อมกับระบุจำนวนด้าน
val dice = Dice(6)
class MainActivity : AppCompatActivity() {
override fun onCreate(savedInstanceState: Bundle?) {
super.onCreate(savedInstanceState)
setContentView(R.layout.activity_main)
val rollButton: Button = findViewById(R.id.button)
rollButton.setOnClickListener {
rollDice()
}
}
private fun rollDice() {
// Create new Dice object with 6 sides and roll it
val dice = Dice(6)
val diceRoll = dice.roll()
// Update the screen with the dice roll
val resultTextView: TextView = findViewById(R.id.textView)
resultTextView.text = diceRoll.toString()
}
class Dice(private val numSide: Int) {
fun roll(): Int {
return (1..numSide).random()
}
}
}
เสร็จเรียบร้อยแล้วกับการสร้าง Dice class พร้อมดัวยตัวแปร numSide และฟังก์ชัน roll () เราได้สร้าง object instance ของ Dice ใหม่ จากนั้นก็เรียกฟังก์ชัน roll () เพื่อสร้างตัวเลขสุ่ม
ขอขอบคุณ Google Developers Training team