از این بخش از مقاله آموزش کاتلین به بعد، به بررسی مفاهیم مرتبط با برنامهنویسی شیءگرا در کاتلین میپردازیم. در ابتدا با مفهوم کلاس، شیوه ایجاد شیء و استفاده از آن در این زبان برنامهنویسی آشنا میشویم.
کاتلین از هر دو پارادایم برنامهنویسی تابعی و شیءگرا پشتیبانی میکند. قابلیتهای کاتلین امکان نوشتن تابعهای مرتبه بالا، انواع مختلف تابعها و لامبدا را فراهم میسازد و به این ترتیب به گزینهای عالی برای سبک برنامهنویسی تابعی تبدیل میشود. اما در این بخش بر روی بررسی مفاهیم سبک برنامهنویسی شیءگرا متمرکز خواهیم شد.
برنامهنویسی شیءگرا
در سبک برنامهنویسی شیءگرا (OOP) یک مسئله پیچیده با ایجاد شیءهایی به مجموعههای کوچکتر تقسیم میشود. این اشیا دو خصوصیت دارند:
- حالت
- رفتار
در ادامه برخی مثالهایی از اشیا را بررسی میکنیم.
- لامپ (Lamp) یک شیء است:
- این شیء میتواند حالتهای روشن (On) و خاموش (Off) داشته باشد.
- این شیء میتواند رفتار روشن کردن (turn on) و خاموش کردن (turn off) را بگیرد.
- دوچرخه (Bicycle) یک شیء است.
- این شیء میتواند حالتهای «دنده کنونی» (current gear)، «دو چرخ» (two wheels)، «تعداد دنده» (number of gear) و بسیاری حالتهای دیگر را داشته باشد.
- این شیء میتواند رفتار «ترمز کردن» (braking)، «پدال زدن» (changing gears)، «تغییر دادن دنده» (changing gears) و بسیاری رفتارهای دیگر را داشته باشد.
در بخشهای بعدی این مقاله آموزش کاتلین در خصوص ویژگیهای مختلف برنامهنویسی شیءگرا از قبیل کپسولهسازی دادهها، وراثت، چندریختی و غیره صحبت خواهیم کرد. در این بخش صرفاً روی مبانی مقدماتی شیءگرایی در کاتلین تمرکز میکنیم.
کلاس کاتلین
پیش از آن که بتوان اشیایی در کاتلین ساخت، باید یک کلاس در این زبان تعریف کرد. کلاس، یک نقشه اولیه برای ساخت شیء محسوب میشود. کلاس را میتوان مانند یک رسم اولیه (پروتوتایپ) از یک خانه تصور کرد. این کلاس شامل جزییاتی در مورد طبقات، درها، پنجرههای و اجزای دیگر خانه دارد. بر اساس این توصیفها میتوان خانه را ساخت. به این ترتیب خانه ساخته شده یک شیء خواهد بود. همان طور که خانههای زیادی را میتوان از روی یک نقشه اولیه واحد ساخت، از روی یک کلاس نیز میتوان اشیای زیادی ایجاد کرد.
شیوه تعریف کلاس در کاتلین چگونه است؟
برای تعریف یک کلاس در کاتلین باید از کلیدواژه class استفاده کنیم:
class ClassName { // property // member function ... .. ...
}
به مثال زیر توجه کنید:
class Lamp {
// property (data member) private var isOn: Boolean = false
// member function fun turnOn() { isOn = true }
// member function fun turnOff() { isOn = false }
}
در مثال فوق یک کلاس با نام Lamp تعریف کردهایم. این کلاس دارای یک مشخصه به نام isOn است که همانند یک متغیر تعریف شده است. همچنین دو تابع عضو به نامهای ()turnOn و ()turnOff دارد.
یک مشخصه در کلاسهای کاتلین یا باید مقداردهی شود و یا به صورت «مجرد» (abstract) اعلان شود. در مثال فوق، مشخصه isOn به صورت False مقداردهی شده است. کلاسها، اشیا، مشخصهها، تابع عضو و غیره، همگی دارای مادیفایرهای «نمایانی» (Visibility) هستند. برای نمونه مشخصه isOn خصوصی است. این بدان معنی است که مشخصه isOn تنها از درون کلاس Lamp میتواند تغییر یابد.
مادیفایرهای دیگر نمایانی در کاتلین به شرح زیر هستند:
- Private – صرفاً از درون خود کلاس قابل مشاهده (دسترسی) است.
- Public – در هر کجا نمایان است.
- Protected – برای کلاس و زیرکلاسهای آن نمایان است.
- Internal – هر کلاینت درون ماژول میتواند به آن دسترسی داشته باشد.
در بخشهای بعدی در مورد مادیفایرهای protected و internal بیشتر صحبت خواهیم کرد. در برنامه فوق، تابعهای عضو ()turnOn و ()turnOff به صورت عمومی (public) هستند، در حالی که مشخصه isOn خصوصی (private) است.
اشیای کاتلین
در زمان تعریف یک کلاس، صرفاً مشخصههای شیء تعریف میشوند و هیچ حافظه یا فضای ذخیرهسازی به آن تخصیص نمییابد. برای دسترسی به تابعهای عوض درون کلاس باید از روی آن اشیایی ایجاد کرد. در ادامه مثالی از ایجاد یک شیء بر مبنای کلاس Lamp میبینید که در بخش قبل تعریف کردیم:
class Lamp {
// property (data member) private var isOn: Boolean = false
// member function fun turnOn() { isOn = true }
// member function fun turnOff() { isOn = false }
}
fun main(args: Array<String>) {
val l1 = Lamp() // create l1 object of Lamp class val l2 = Lamp() // create l2 object of Lamp class
}
برنامه فوق دو شیء به نامهای l1 و l2 از روی کلاس Lamp ایجاد میکند. مشخصه isOn برای هر دو لامپ l1 و l2 به صورت false است.
شیوه دسترسی به اعضا چگونه است؟
امکان دسترسی به مشخصهها و تابعهای عضو یک کلاس با استفاده از نماد نقطه (.) وجود دارد. به مثال زیر توجه کنید:
l1.turnOn()
گزاره فوق تابع ()turnOn را روی شیء l1 فرا میخواند. به مثال زیر نیز توجه کنید:
l2.isOn = true
در اینجا مقدار مشخصه isOn مربوط به شیء l2 را به صورت true تنظیم میکنیم. توجه کنید که مشخصه isOn به صورت خصوصی تعریف شده است و اگر تلاش کنید از خارج از کلاس به آن دسترسی داشته باشید، یک استثنا ایجاد میشود.
مثالی از کلاس و شیء کاتلین
class Lamp {
// property (data member) private var isOn: Boolean = false
// member function fun turnOn() { isOn = true }
// member function fun turnOff() { isOn = false }
fun displayLightStatus(lamp: String) { if (isOn == true) println("$lamp lamp is on.") else println("$lamp lamp is off.") }
}
fun main(args: Array<String>) {
val l1 = Lamp() // create l1 object of Lamp class val l2 = Lamp() // create l2 object of Lamp class
l1.turnOn() l2.turnOff()
l1.displayLightStatus("l1") l2.displayLightStatus("l2")
}
خروجی برنامه فوق به صورت زیر است:
l1 Lamp is on. l2 Lamp is off.
در این بخش در خصوص برنامه فوق برخی توضیحها را ارائه میکنیم:
- ابتدا کلاس Lamp ایجاد میشود.
- این کلاس دارای مشخصه isOn و سه تابع عضو به صورت ()turnOn() ،turnOff و ()displayLightStatus است.
- دو شیء l1 و l2 مربوط به کلاس Lamp در تابع ()main ایجاد شدهاند.
- در ادامه تابع ()turnOn با استفاده از شیء l1 به صورت ()l1.turnOn فراخوانی میشود. این متد موجب میشود که متغیر وهلهای isOn مربوط به شیء l1 به صورت true تنظیم شود.
- سپس تابع ()turnOff با استفاده از شیء l2 به صورت ()l2.turnOff فراخوانی میشود. این متد نیز موجب میشود که متد وهلهای isOff مربوط به شیء l2 به صورت false تنظیم شود.
- در نهایت تابع ()displayLightStatus برای هر دو شیء l1 و l2 فراخوانی میشود و پیام مناسبی بسته به این که مشخصه isOn مقدار true یا false داشته باشد، تنظیم میکند.
توجه کنید که مشخصه isOn درون کلاس به صورت false مقداردهی میشود. زمانی که یک شیء از کلاس ایجاد میشود، مشخصه isOn مربوط به آن شیء به صورت خودکار روی false تنظیم میشود. بنابراین لزومی به فراخوانی ()turnOff برای تنظیم مقدار مشخصه isOn به مقدار false وجود نخواهد داشت.
به مثال زیر توجه کنید:
class Lamp {
// property (data member) private var isOn: Boolean = false
// member function fun turnOn() { isOn = true }
// member function fun turnOff() { isOn = false }
fun displayLightStatus() { if (isOn == true) println("lamp is on.") else println("lamp is off.") }
}
fun main(args: Array<String>) {
val lamp = Lamp() lamp.displayLightStatus()
}
خروجی برنامه فوق چنین است:
lamp is off.
بدین ترتیب به انتهای این بخش از مقاله آموزش کاتلین میرسیم. در این بخش با مفاهیم مقدماتی برنامهنویسی شیءگرا در کاتلین آشنا شدیم.