Class ใน Kotlin เป็นพื้นฐานของการทำแอพเชิง Object โดยกำหนดพิมพ์เขียว (blueprint) สำหรับการสร้าง Object ที่มีลักษณะการทำงานและคุณสมบัติร่วมกัน ในบทความนี้ จะสำรวจ Class ใน Kotlin และวิธีการรับทำแอพ OOP
การสร้างคลาส (Class)ใน Kotlin
ใน Kotlin สามารถสร้างคลาสโดยใช้คีย์เวิร์ด “class” ตามด้วยชื่อคลาส ตัวอย่าง:
class Person {
// class body
}
เนื้อหาของคลาส (class body) เป็นที่ที่กำหนดคุณสมบัติ (properties) และวิธีการ (methods) ของคลาส คุณสมบัติคือตัวแปรที่เก็บข้อมูล และเมธอดคือฟังก์ชันที่ดำเนินการกับข้อมูล มากำหนดคุณสมบัติและวิธีการบางอย่างสำหรับคลาส Person:
class Person(val name: String, var age: Int) {
fun speak() {
println("Hello, my name is $name")
}
fun celebrateBirthday() {
age++
println("It's my ${age}th birthday!")
}
}
ในตัวอย่างนี้ได้กำหนดคลาส Person ด้วยคุณสมบัติสองอย่าง: ชื่อและอายุ คีย์เวิร์ด “val” ก่อนคุณสมบัติชื่อหมายความว่าเป็นคุณสมบัติแบบอ่านอย่างเดียว ขณะที่คีย์เวิร์ด “var” ก่อนคุณสมบัติ age หมายความว่าสามารถแก้ไขได้
ยังกำหนดสองวิธี (methods): speak และ celebrateBirthday วิธี (methods) speak จะพิมพ์คำทักทายพร้อมชื่อของบุคคลนั้น และวิธี (methods) celebrateBirthday จะเพิ่มคุณสมบัติอายุและพิมพ์ข้อความ
การสร้าง Object จากคลาส
เมื่อกำหนดคลาสแล้ว สามารถสร้างออบเจกต์จากคลาสนั้นได้ ในการสร้างออบเจกต์ใน Kotlin ให้ใช้คีย์เวิร์ด “new” ตามด้วยชื่อคลาสและอาร์กิวเมนต์ที่ตัวสร้างคลาสที่ต้องการ อย่างไรก็ตาม Kotlin มีวิธีการสร้างวัตถุที่รัดกุมมากขึ้น ซึ่งเรียกว่าตัวสร้างหลัก (primary constructor)
ตัวสร้างหลัก (primary constructor) ถูกกำหนดไว้ในส่วนหัวของคลาสและสามารถใช้พารามิเตอร์ตั้งแต่หนึ่งตัวขึ้นไป ใช้เพื่อเริ่มต้นคุณสมบัติของคลาสเมื่อสร้างออบเจกต์ นี่คือวิธีที่สามารถสร้างออบเจกต์จากคลาส Personโดยใช้ตัวสร้างหลัก (primary constructor):
val person1 = Person("Alice", 30)
val person2 = Person("Bob", 25)
person1.speak() // Output: Hello, my name is Alice
person2.celebrateBirthday() // Output: It's my 26th birthday!
ในตัวอย่างนี้ ได้สร้างอ็อบเจกต์คลาส Person สองรายการ: person1 และ person2 ได้ส่งค่าชื่อและอายุไปยังตัวสร้างหลักเพื่อเริ่มต้นคุณสมบัติ จากนั้นสามารถเรียกใช้เมธอดบนวัตถุเหล่านี้เพื่อดำเนินการกับข้อมูลได้
Inheritance
Kotlin รองรับการสืบทอด (Inheritance) ซึ่งช่วยให้สร้างคลาสใหม่ที่สืบทอดคุณสมบัติและวิธีการของคลาสที่มีอยู่ หากต้องการสืบทอดคลาสใน Kotlin ให้ใช้คีย์เวิร์ด “open” ก่อนชื่อคลาส จากนั้นใช้คีย์เวิร์ด “extends” ตามด้วยชื่อคลาสพื้นฐาน นี่คือตัวอย่าง:
open class Animal(val name: String) {
fun speak() {
println("$name makes a sound")
}
}
class Dog(name: String) : Animal(name) {
override fun speak() {
println("$name barks")
}
}
ในตัวอย่างนี้ ได้กำหนดคลาส Animal ด้วยเมธอด speak และคลาส Dog ที่สืบทอดมาจากคลาส Animal ได้แทนที่เมธอด speak ในคลาส Dog เพื่อพิมพ์ข้อความอื่น
เมื่อสร้างออบเจกต์ของคลาส Dog จะสามารถเรียกเมธอด speak จากทั้งคลาส Dog และ Animal ได้:
val dog = Dog("Dog")
dog.speak() // Output: Dog barks
ในตัวอย่างนี้ ได้สร้าง Dog object และเรียกเมธอด speak โดยเมธอด speak ที่ถูกแทนที่ในคลาส Dog เรียกว่า “Dog barks” แทนที่จะเป็น “Animal makes a sound.”
ตัวดัดแปลงการเข้าถึง (access modifiers) ที่มีอยู่ใน Kotlin
ใน Kotlin มีตัวดัดแปลงการเข้าถึงอื่นๆ อีกหลายตัวที่สามารถใช้เพื่อควบคุมการมองเห็นและการสืบทอดคลาสและสมาชิกของคลาส นี่คือตัวดัดแปลงการเข้าถึงบางส่วนที่มีอยู่ใน Kotlin:
- public: ตัวแก้ไขการเข้าถึงเริ่มต้น (default) ซึ่งหมายความว่าโค้ดอื่น ๆ ทั้งหมดในโครงการสามารถมองเห็นคลาสหรือสมาชิกได้
- private: คลาสหรือสมาชิกจะมองเห็นได้ภายในไฟล์เดียวกับที่มีการประกาศเท่านั้น
- protected: คลาสหรือสมาชิกสามารถมองเห็นได้ภายในไฟล์เดียวกันรวมถึงคลาสย่อย (subclasses) ของคลาส
- internal: คลาสหรือสมาชิกจะมองเห็นได้ภายในโมดูลเดียวกันเท่านั้น (เช่น หน่วยโค้ดที่คอมไพล์แล้ว)
นอกจากตัวดัดแปลงการเข้าถึงเหล่านี้แล้ว Kotlin ยังมีตัวปรับแต่งเพิ่มเติมอีกสองตัวที่สามารถใช้ร่วมกับตัวปรับแต่งด้านบน:
- open: อนุญาตให้คลาสหรือสมาชิกถูกคลาสย่อยหรือแทนที่ (overridden) โดยคลาสอื่น
- final: ป้องกันไม่ให้คลาสหรือสมาชิกถูกคลาสย่อยหรือถูกแทนที่โดยคลาสอื่น
คุณสมบัติคลาสใน OOP
การทำแอพเชิงวัตถุ (OOP) เป็นกระบวนทัศน์การรับทำแอพที่ยึดตามแนวคิดของวัตถุซึ่งสรุปข้อมูลและพฤติกรรม OOP มีคุณสมบัติที่หลากหลายในการสร้างแอปพลิเคชันซอฟต์แวร์แบบโมดูลาร์ ใช้ซ้ำได้ และปรับขนาดได้ ต่อไปนี้คือรายการคุณสมบัติหลักของคลาสใน OOP:
1. Abstraction
Abstraction เป็นกระบวนการซ่อนรายละเอียดการใช้งานของวัตถุและเปิดเผยข้อมูลที่จำเป็นต่อผู้ใช้เท่านั้น ใน Kotlin การทำสิ่งที่เป็นนามธรรม (Abstraction) สามารถทำได้ผ่านอินเทอร์เฟซและคลาสนามธรรม (Abstraction)
interface Animal {
fun speak()
}
class Dog : Animal {
override fun speak() {
println("Dog barks")
}
}
ในตัวอย่างนี้ มีอินเทอร์เฟซสำหรับ Animal ที่มีวิธีการ speak และคลาส Dog ที่ใช้อินเทอร์เฟซสำหรับ Animal และแทนที่ (override) วิธีการ speak การใช้วิธี speak ในคลาส Dog ถูกซ่อนจากผู้ใช้ และเปิดเผยเฉพาะข้อมูลที่จำเป็น (เช่น Dog สามารถ speak ได้)
คลาสนามธรรม (abstract class) คือคลาสที่ไม่สามารถสร้างอินสแตนซ์ได้ และสามารถใช้เป็นคลาสพื้นฐานสำหรับคลาสอื่นเท่านั้น ใน Kotlin สามารถกำหนดคลาสนามธรรม (abstract class) โดยใช้คีย์เวิร์ด “abstract” ตัวอย่าง:
abstract class Vehicle {
abstract fun start()
abstract fun stop()
}
ในตัวอย่างนี้ มีคลาสนามธรรม (abstract class) ของ Vehicle ที่มีวิธีการนามธรรม (abstract) สองวิธีชื่อ “start” และ “stop” คลาสใด ๆ ที่ขยายคลาสของยานพาหนะจะต้องจัดให้มีการใช้งานสำหรับวิธีการเริ่มต้นและหยุด
2. Encapsulation
Encapsulation เป็นกระบวนการของการห่อ (wrapping) ข้อมูลและวิธีการภายในหน่วยเดียว (เช่น คลาส) และควบคุมการเข้าถึงโดยใช้ตัวดัดแปลงการเข้าถึง (public, private, protected) ใน Kotlin สามารถใช้ตัวดัดแปลงการเข้าถึงเพื่อให้ได้การห่อหุ้ม (wrapping)
มีตัวแก้ไขการเข้าถึง (access modifiers) สามตัวใน Kotlin:
- public: สมาชิกสาธารณะสามารถเข้าถึงได้จากทุกที่ในโค้ด
- private: สมาชิกส่วนตัวสามารถเข้าถึงได้จากภายใน class เท่านั้น
- protected: สมาชิกที่ได้รับการป้องกันสามารถเข้าถึงได้จากภายใน class และ subclasses
class Person {
var name: String = ""
private set
fun setName(name: String) {
this.name = name
}
}
ในตัวอย่างนี้ มีคลาส Person ที่มีคุณสมบัติ name ที่เป็นส่วนตัว และเมธอด setName ที่สามารถใช้เพื่อตั้งค่าคุณสมบัติชื่อ คุณสมบัติชื่อสามารถเข้าถึงได้จากภายในคลาสเท่านั้น ในขณะที่เมธอด setName สามารถใช้เพื่อตั้งค่าคุณสมบัติชื่อจากภายนอกคลาส
ส่วนที่น่าสนใจของคลาสนี้คือตัวดัดแปลง private set ที่ตามหลังการประกาศคุณสมบัติ name ซึ่งหมายความว่าคุณสมบัติชื่อสามารถอ่านได้จากภายนอกคลาส แต่สามารถตั้งค่าได้จากภายในคลาสเท่านั้น
3. Inheritance
การสืบทอด (Inheritance) เป็นกระบวนการสร้างคลาสใหม่จากคลาสที่มีอยู่ และสืบทอดคุณสมบัติและเมธอดของคลาสพื้นฐาน ใน Kotlin สามารถใช้ไวยากรณ์ “class : base class” เพื่อรับการสืบทอด
open class Animal {
open fun speak() {
println("Animal makes a sound")
}
}
class Dog : Animal() {
override fun speak() {
println("Dog barks")
}
}
ในตัวอย่างนี้ มีคลาส Animal ที่มีวิธีการ speak ที่พิมพ์ว่า “Animal makes a sound” คลาส Dog สืบทอดคลาส Animal และแทนที่วิธีการ speak เพื่อพิมพ์ “Dog bars”
4. Polymorphism
ความแตกต่าง (Polymorphism) คือความสามารถของวัตถุในรูปแบบและพฤติกรรมที่แตกต่างกันตามบริบท ความหลากหลายช่วยในการเขียนโค้ดที่ยืดหยุ่นและปรับให้เข้ากับสถานการณ์ต่างๆ ใน Kotlin สามารถบรรลุความหลากหลายผ่านการสืบทอด (inheritance) และอินเทอร์เฟซ (interfaces)
นี่คือตัวอย่างที่แสดงให้เห็นถึงความหลากหลายโดยใช้การสืบทอด (inheritance) :
open class Shape {
open fun draw() {
println("Drawing a shape")
}
}
class Circle : Shape() {
override fun draw() {
println("Drawing a circle")
}
}
class Rectangle : Shape() {
override fun draw() {
println("Drawing a rectangle")
}
}
ในตัวอย่างนี้ มีคลาส Shape ที่มีวิธีการ draw ที่พิมพ์ “Drawing a shape” คลาส Circle และ Rectangle ขยายคลาส Shape โดยใช้ไวยากรณ์ “class : base class” และแทนที่เมธอดการ draw เพื่อพิมพ์ “Drawing a circle” และ “Drawing a rectangle” ตามลำดับ
นี่คือตัวอย่างที่แสดงให้เห็นถึงความหลากหลายโดยใช้อินเทอร์เฟซ:
interface Shape {
fun draw()
}
class Circle : Shape {
override fun draw() {
println("Drawing a circle")
}
}
class Rectangle : Shape {
override fun draw() {
println("Drawing a rectangle")
}
}
ในตัวอย่างนี้ มีอินเทอร์เฟซ Shape พร้อมวิธีการ draw คลาส Circle และ Rectangle ใช้อินเทอร์เฟซ Shape และเตรียมการนำไปใช้เองสำหรับเมธอด draw
5. Constructor
ตัวสร้าง (Constructor) เป็นวิธีการพิเศษ (special method) ที่ใช้ในการเริ่มต้น (initialize) คุณสมบัติ (properties) ของคลาสเมื่อสร้างวัตถุ ใน Kotlin สามารถกำหนดตัวสร้างหลัก (primary) และตัวสร้างรอง (secondary) ได้
class Person(var name: String, var age: Int) {
init {
println("Person is created with name: $name and age: $age")
}
constructor(name: String) : this(name, 0) {
println("Person is created with name: $name")
}
}
ในตัวอย่างนี้ มีคลาส Person ที่มีตัวสร้างหลักที่รับพารามิเตอร์สองตัว (ชื่อและอายุ) และตัวสร้างรองที่รับเฉพาะพารามิเตอร์ชื่อ บล็อก init ในตัวสร้างหลักใช้เพื่อพิมพ์ข้อความเมื่อ Person object ถูกสร้างขึ้น
6. Method
เมธอด (Method) คือฟังก์ชันสมาชิกของคลาสที่ทำงานเฉพาะ วิธีการ (Method)ใน Kotlin สามารถกำหนดได้ภายในเนื้อหาของคลาสและสามารถเข้าถึงคุณสมบัติของคลาสได้
class Calculator {
fun add(a: Int, b: Int): Int {
return a + b
}
}
ในตัวอย่างนี้ ได้กำหนดคลาส Calculator ด้วยเมธอดที่เรียกว่า add ซึ่งรับพารามิเตอร์ a และ b สองตัวและส่งกลับผลรวม
7. Property
คุณสมบัติ (Property) คือตัวแปรสมาชิก (member variable) ของคลาสที่เก็บข้อมูล ใน Kotlin สามารถกำหนดคุณสมบัติโดยใช้คีย์เวิร์ด var และ val สำหรับคุณสมบัติที่ไม่เปลี่ยนรูปและไม่เปลี่ยนรูปตามลำดับ
class Person {
var name: String = ""
val age: Int = 0
}
ในตัวอย่างนี้ ได้กำหนดคลาส Person ด้วยคุณสมบัติสองอย่าง: name (คุณสมบัติที่ไม่เปลี่ยนรูป) และage (คุณสมบัติที่ไม่เปลี่ยนรูป) คุณสมบัติจะเริ่มต้นด้วยค่าเริ่มต้น
8. Interface
อินเทอร์เฟซ (Interface) คือสัญญา (contract) ที่กำหนดชุดของเมธอดและคุณสมบัติที่คลาสต้องนำไปใช้ ใน Kotlin อินเทอร์เฟซสามารถกำหนดได้โดยใช้คีย์เวิร์ด Interface
interface Shape {
fun area(): Double
fun perimeter(): Double
}
ในตัวอย่างนี้ ได้กำหนดอินเทอร์เฟซ Shape ด้วยสองวิธี: area และ perimeter คลาสใดๆ ที่ใช้อินเทอร์เฟซนี้จะต้องมีการใช้งานสำหรับเมธอดเหล่านี้
9. Abstract class
คลาสนามธรรม (Abstract class) คือคลาสที่ไม่สามารถสร้างอินสแตนซ์ได้ แต่ใช้เป็นคลาสพื้นฐานสำหรับคลาสอื่น ใน Kotlin ได้เท่านั้น คลาสนามธรรม (Abstract class) สามารถกำหนดได้โดยใช้คีย์เวิร์ด abstract
abstract class Shape {
abstract fun area(): Double
abstract fun perimeter(): Double
}
ในตัวอย่างนี้ได้กำหนดคลาสนามธรรม (Abstract class) ของ Shape ด้วยวิธีการนามธรรม (abstract methods) สองวิธี: areaและ perimeter คลาสใด ๆ ที่ขยายคลาสนี้จะต้องมีการใช้งานสำหรับเมธอดเหล่านี้
10. Static class
คลาสสแตติกคือคลาสที่สามารถเข้าถึงได้โดยไม่ต้องสร้าง object ใน Kotlin คลาสสแตติกสามารถกำหนดได้โดยใช้คีย์เวิร์ด object
object MathUtils {
fun add(a: Int, b: Int): Int {
return a + b
}
}
ในตัวอย่างนี้ ได้กำหนดคลาสสแตติกของ MathUtils ด้วยเมธอดชื่อ add ที่รับพารามิเตอร์ a และ b สองตัวและส่งกลับผลรวม สามารถเข้าถึงคลาส MathUtils ได้โดยไม่ต้องสร้าง object
เมื่อใดควรใช้ interface หรือ abstract class
ทั้ง interface และคลาส abstractใช้สำหรับการ abstraction และกำหนด contracts ระหว่างคอมโพเนนต์ในการทำแอพเชิงวัตถุ อย่างไรก็ตาม มีความแตกต่างบางประการในการใช้งาน ซึ่งอาจส่งผลต่อการตัดสินใจเลือกใช้อันใดอันหนึ่งมากกว่าอันอื่น
interface จะใช้เมื่อ:
- ต้องการกำหนดสัญญาสำหรับพฤติกรรมที่คลาสต่างๆ นำไปใช้ได้
- ต้องการกำหนดสัญญาสำหรับชุดของวิธีการที่เกี่ยวข้องซึ่งไม่ได้ใช้งานร่วมกัน
- ต้องการกำหนดสัญญาสำหรับพฤติกรรมที่ควรเปิดเผยต่อสาธารณะและใช้โค้ดอื่น
- ต้องการสืบทอดหลายรายการ เนื่องจาก Kotlin ไม่รองรับการสืบทอดหลายรายการในระดับคลาส
interface Animal {
fun makeSound()
}
class Dog: Animal {
override fun makeSound() {
println("Bark")
}
}
class Cat: Animal {
override fun makeSound() {
println("Meow")
}
}
ในตัวอย่างนี้ ได้กำหนด interface Animal ด้วยเมธอด makeSound ที่ต้องนำไปใช้โดยคลาสใดๆ ที่ใช้ interface Animal คลาส Dog and Cat ใช้อินเทอร์เฟซ Animal และจัดเตรียมเมธอด makeSound ของตัวเอง
abstract class ใช้เมื่อ:
- ต้องการจัดเตรียมคลาสพื้นฐานทั่วไปสำหรับกลุ่มของคลาสที่เกี่ยวข้องกัน
- ต้องการกำหนดชุดของเมธอดที่ต้องนำไปใช้โดยคลาสที่ได้รับ
- ต้องการกำหนดชุดของวิธีการที่ใช้ร่วมกัน แต่สามารถถูกแทนที่โดยคลาสที่ได้รับ
- ต้องการจัดเตรียมคลาสพื้นฐานที่มีการใช้งานเริ่มต้นบางอย่างที่สามารถแทนที่ด้วยคลาสที่ได้รับมา
abstract class Shape {
abstract fun area(): Double
abstract fun perimeter(): Double
open fun draw() {
println("Drawing a shape")
}
}
class Circle(val radius: Double) : Shape() {
override fun area() = Math.PI * radius * radius
override fun perimeter() = 2 * Math.PI * radius
}
ในตัวอย่างนี้ ได้กำหนด abstract class ของ Shape ด้วยเมธอด abstract สองวิธี ได้แก่ area และ perimeter ซึ่งคลาสใดๆ ก็ตามที่มาจากคลาส Shape จะต้องนำไปใช้ คลาส Circle ขยายคลาส Shape และจัดเตรียมการใช้งานarea และ perimeter ของตัวเอง คลาส Shape ยังจัดเตรียมการใช้งานเริ่มต้นของวิธีการวาด ซึ่งสามารถแทนที่ด้วยคลาส Circle ได้หากจำเป็น
โดยสรุป Kotlin ให้ไวยากรณ์ที่มีประสิทธิภาพและกระชับสำหรับการสร้างคลาสที่ใช้ประโยชน์จากหลักการทำแอพเชิงวัตถุ ด้วยการสนับสนุนคุณสมบัติ ตัวสร้าง การสืบทอด อินเทอร์เฟซ และคลาสนามธรรม Kotlin ช่วยให้การรับทำแอพสามารถสร้างโค้ดที่มีโครงสร้างดีและบำรุงรักษาได้ คลาส Kotlin ยังได้รับประโยชน์จากฟีเจอร์ต่างๆ เช่น คลาสข้อมูล คลาสที่ปิดสนิท และออบเจกต์ร่วม ซึ่งให้ฟังก์ชันเพิ่มเติมและลดโค้ดสำเร็จรูป ไม่ว่าจะกำลังสร้างฟังก์ชันยูทิลิตี้ขนาดเล็กหรือแอปพลิเคชันขนาดใหญ่ คลาส Kotlin สามารถช่วยจัดระเบียบโค้ดและทำแอพที่มีประสิทธิภาพได้อย่างดี