توابع در زبان برنامه نویسی Kotlin
در مقاله قبل دستورات مقدماتی زبان برنامه نویسی Kotlin را مورد بررسی قرار دادیم. در این مقاله نیز قصد داریم تا توابع را در زبان Kotlin مورد بررسی قرار دهیم.
یکی از مهم ترین بخش های هر زبان برنامه نویسی توابع و شیوه تعریف آنها است. ساختار توابع در زبان Kotlin به این صورت است:
access_level fun function_name(var1:var1_type,var2:var2_type,...) :return_type{ return if needed }
- access_level : مشخص میکند که سطح دسترسی به این تابع به چه صورتی است. در صورتی که از مقداری برای آن تعیین نشود٬ به صورت public تعریف میشود
- fun : کلمه کلیدی برای تعریف که الزامی است
- function_name : نام تابع را مشخص میکند
- var1, var1_type : پارامتر های دریافتی تابع هستند که var1 نام پارامتر و var1_type نوع آن را مشخص میکند. همچنین میتوانیم متغیر های دیگر را با استفاده از (,) از یکدیگر جدا کنیم
- return_type : نوع مقداری که این تابع برمیگرداند را مشخص میکند. باید به این نکته توجه داشته باشیم که در این زبان٬ کلمه کلیدی void وجود ندارد و بجای آن از Unit استفاده میشود. البته میتوان بدون قرار دادن آن نیز تابع را تعریف کرد
- return : در پایان اگر نیاز به برگرداندن مقداری بود٬ میتوانیم از return استفاده کنیم
همچنین یکی از امکاناتی که kotlin در اختیار ما قرار میدهد٬ تعریف توابع به صورت یک خطی است:
fun add(var1: Int, var2: Int): Int = var1 + var2
در کد فوق از کلمه return استفاده نمیکنیم.
میتوانیم برای پارامتر ها٬ مقدار پیش فرض تعیین کنیم تا در صورتی که مقداری به این پارامتر٬ به هنگام فراخوانی متد٬ اختصاص نیافت٬ تابع با این مقدار پیش فرض کار خود را آعاز کند:
fun showMessage(message: String = "no message") { println(message) }
و فراخوانی آن به این صورت خواهد بود:
showMessage() // no message showMessage(" hi ") // hi
توابع در Kotlin نمیتوانند مقدار null برگردانند. برای اینکه توابع را nullable تعریف کنیم٬ نیاز است تا نوع متغیری که تابع برمیگرداند٬ از نوع nullable باشد:
fun getMessage(): String? { return null }
در زبان برنامه نویسی جاوا٬ ترتیب ارجاع متغیر ها به تابع٬ باید بر اساس تعریف تابع باشد. به این معنا ک تغییر در تقدم ارسال متغیر ها نسب به یکدیگر٬ باعث خطا منطقی و یا کامپایلری خواهد شد. اما در Kotlin میتوانیم با مشخص کردن نام هر پارامتر به هنگام فراخوانی تابع٬ از رعایت ترتیب پارامتر ها صرف نظر کنیم. برای مثال اگر تابع زیر را داشته باشیم:
fun stringAndInt(stringVar: String, intVar: Int) { println("string is : $stringVar and int is : $intVar") }
میتوانیم به این دو صورت آن را فراخوانی کنیم:
stringAndInt("i'm string", 2) stringAndInt(intVar = 3,stringVar = "i'm string")
یکی از ویژگی هایی ک در زبان برنامه نویسی جاوا وجود دارد این است که میتواینم تعداد نا مشخصی از متغیر ها را به یک متد ارسال کنیم که به صورت یک آرایه در اختیار متد قرا میگیرد:
public void variables(int... numbers) { for (int number : numbers) { System.out.println(number); } }
و فراخوانی این متد به این صورت است:
variables(1, 2, 3, 4, 5, 6, 7, 8, 9);
در زبان Kotlin نیز میتوانیم توابع این چنینی را تعریف کنیم:
fun variables(vararg numbers: Int) { for (number in numbers) { println(number) } }
در اینجا با استفاده از کلمه کلیدی varargs این متد را پیاده سازی میکنیم و شیوه فراخوانی آن نیز به همان صورت است که در جاوا استفاده کردیم.
توابع تو در تو
یکی از ویژگی های زبان برنامه نویسی Kotlin این است که میتوانیم یک تابع را درون تابعی دیگر تعریف کنیم. برای مثال میتوانیم کد فوق را به این صورت تغییر دهیم:
fun variables(vararg numbers: Int) { var sum = 0 fun add(num: Int) { sum += num } for (number in numbers) { add(number) } println("sum of numbers : $sum") }
اما نکته اینجاست که این دستور چگونه به زبان جاوا ترجمه میشود. کد فوق را میتوانیم به این صورت در زبان جاوا پیاده سازی کنیم:
public void variables(int... numbers) { int[] sum = new int[1]; Consumer<Integer> add = (num) -> sum[0] += num; for (int number : numbers) { add.accept(number); } System.out.println("sum of numbers : " + sum[0]); }
در حقیقت در اینجا میتوانیم از Functional Interface ها استفاده کنیم. اگر با Functional Interface ها آشنایی ندارید میتوانید این مقاله را مطالعه کنید.
توابع بازگشتی
گاهی برخی از الگوریتم ها اگر به صورت بازگشتی تعریف شوند بهینه تر هستند. الگوریتم هایی که بر پایه تکرار یک دستور هستند در این دسته قرار میگیرند. نمونه ای از این الگوریتم ها پیاده سازی فاکتوریل است که فرمول آن ضرب عدد در عدد قبلی خود است تا وقتی به ۱برسد و آخرین ضرب٬ ضرب عدد حاصل در ۱ است.
اگر بخواهیم توابع بازگشتی را در kotlin پیاده سازی کنیم. یکی از ابزاری ک kotlin در اختیار ما قرار میدهد تا بتواینم این توابع را در شرایط بهینه پیاده سازی کنیم٬ استفاده از tailrec است. یکی از چالش هایی که در استفاده از توابع بازگشتی با آن مواجه هستیم٬ بروز خطای stack overflow است. اما با استفاده از این کلمه کلیدی٬ Kotlin این اطمینان را به ما می دهد که همچنی خطایی رخ نمیدهد. وقتی از tailrec استفاده میکنیم٬ کامپایلر الگوریتم بازگشتی را با استفاده از دستورات تکرار در بهینه ترین حالت ممکن اجرا میکند. اما باید این نکته را مد نظر داشته باشیم که tailrec در صورتی که ساختار تعیین شده برای آن را رعایت کنیم٬ قابل استفاده است. ساختار تعیین شده برای استفاده از tailrec به این صورت است که متد باید در آخرین خط نوشته شد درون آن٬ خود را فراخوانی کند. به این معنا ک پس از فراخوانی متد٬ توسط خودش٬ کد دیگری نوشته نشود:
tailrec fun factorial(number: Int, acm: Int): Int { val result = number * acm if (number <= 1) { return result } else { return factorial(number - 1, result) } }
میتوانیم این متد را به این صورت بنویسیم:
fun fact(number: Int): Int { tailrec fun factorial(number: Int, acm: Int): Int { val result = number * acm return if (number <= 1) { result } else { factorial(number - 1, result) } } return factorial(number, 1) }
توجه داشته باشید٬ بهتر است وقتی میخواهیم از دستورات شرطی برای برگرداندن نتیجه استفاده کنیم٬ بهتر است return را پیش از if استفاده کنیم.
متد به عنوان پارامتر
در Kotlin میتوانیم یک تابع را به عنوان یک پارامتر به تابعی دیگر ارسال کنیم:
fun addAndPower(number: Int, function: (a: Int) -> Int): Int { return function(number) + number } val powerFunc = { num: Int -> num * num } println("result : ${addAndPower(2, powerFunc)}")
اگر بخواهیم چنین کدی را در جاوا پیاده سازی کنیم٬ میتوانیم از Functional Interface ها استفاده کنیم:
public int addAndPower(int number, Function<Integer, Integer> function) { return number * function.apply(number); }
و این چنین فراخوانی کنیم:
addAndPower(2, (number -> number * number));
در این مقاله سعی بر این شد تا با مفهوم توابع و شیوه استفاده از آنها آشنا شویم.
با ما همراه باشید.
مطالب زیر را حتما مطالعه کنید
حسگرها و فناوریهای پوشیدنی و کاربردهای آنها در پزشکی
نکاتی که باید پیش از دانلود نمودار ER بدانید
۵ راه کسب درآمد از برنامه نویسی
پایگاه داده (Data Base) چیست؟
برنامه نویسی چیست؟
آموزش برنامهنویسی | برنامهنویسی چیست و چگونه میتوان آنرا فراگرفت؟
2 Comments
Join the discussion and tell us your opinion.
دیدگاهتان را بنویسید لغو پاسخ
برای نوشتن دیدگاه باید وارد بشوید.
جناب رجبی تشکر بابت پستا و مطالب خوبتون. در حال حاضر بیشتر جاهایی که دنبال برنامه نویس اندروید هستند شرایط رو زدند توانایی کار با react native و اصلا صحبتی از جاوا یا کاتلین نشده! به نظر شما لازمه که یه برنامه نویس اندروید با جاوا یا کاتلین مهاجرت کنه و به سمت react بره؟ react هیچ برتری خاصی نسبت به کاتلین یا جاوا داره؟ به نظرتون کسی که میخواد استارت بزنه بهتره از کدومش شروع کنه؟ آیا برنامه هایی که با react نوشته میشه قدرت و بازدهی اونایی که با جاوا یا کاتلین نوشته میشه رو دارن؟ آینده کدومش بهتره؟
سلام وقت بخیر. پوزش بابت تاخیر در پاسخ. همیشه برای پیاده سازی یک اپلیکیشن ( چه سمت کلاینت و چه سمت سرور ) گزینه های زیادی وجود داره. اینکه چه زبانی برای پروژه انتخاب بشه به بزرگی پروژه٬ اهمیت توسعه اون در آینده٬ شیوه نگهداری و باقی عوامل مدیریتی وابسته هست. بازار برنامه نویسی اندروید به صورت native هنوز هم بازار زنده و فعالی هست و نمیشه اینو گفت که react native اومده و جای اونو گرفته. یکی از بحث های خیلی مهم شیوه نگهداری و معماری هست که میتونیم به پروژه ها در ساختار native بدیم. خب ممکنه توی بعضی آگهی ها برنامه نویس hybrid بخوان و علتش هم میتونه اهمیت یک شکل بودن و رسیدن همزمان محصول ios و اندروید باشه اون هم توسط یک برنامه نویس. همچنین بهتر رقیب اصلی برای react native توی حوزه خودش٬ flutter بدونیم. اما قیاس بین برنامه نویسی native و hybrid چیزی نیست که بخوایم به صورت یک قانون و یا حکم کلی بیان کنیم. مسلما زبان javaScript طبق آمار stackoverflow محبوب ترین زبان جهانه و به طبع خیلی جاها باید از مزایای react native هم گفته بشه. من شخصا react native کار نکردم و علاقه ای هم به کار در اون ندارم اما چیزی که به وضوح مشخصه اینه که برنامه نویسی اندروید به صورت native حتی با اومدن react native باز هم قدرت خودش حفظ کرده.