الدوال (Functions) في لغة Kotlin

من موسوعة حسوب
< Kotlin
مراجعة 03:30، 24 مارس 2018 بواسطة Nourtam (نقاش | مساهمات) (أنشأ الصفحة ب'<noinclude>{{DISPLAYTITLE:الدوال (Functions) في لغة Kotlin}}</noinclude> == التصريح عن الدوال (Function Declarations) == يُصرَّح عن ا...')
(فرق) → مراجعة أقدم | المراجعة الحالية (فرق) | مراجعة أحدث ← (فرق)
اذهب إلى التنقل اذهب إلى البحث

التصريح عن الدوال (Function Declarations)

يُصرَّح عن الدوال في لغة Kotlin باستخدام الكلمة المفتاحيّة fun كما يلي:

fun double(x: Int): Int {
    return 2 * x
}

استخدام الدوال (Function Usage)

يكون استدعاء الدوال كما في أيّ لغة برمجةٍ أخرى بالشكل:

val result = double(2)

أمّا استدعاء الدوال من الأصناف فيعتمد على المعامل . كما في الشيفرة:

Sample().foo() // إنشاء كائنٍ من الصنف واستدعاء الدالة عبره

المتحوِّلات الوسيطة (Parameters)

تُعرَّف المتحولات الوسيطة بالصيغة المُعتمدَة في لغة Pascal وهي name: type ، ويُفصَل فيما بينها بالفاصلة , كما ويجب التحديد الصريح لنوع كلّ منها، مثل:

fun powerOf(number: Int, exponent: Int) {
...
}

المتحولات الافتراضيّة (Default Arguments)

قد تحتوي المتحولات الوسيطة (parameters) قيمًا افتراضيّةً تُستخدَم عند حذف المتحول (argument) الموافِق لها، وهذا يسمح بتقليل عمليات التحميل الزائد (overloading) مقارنةً باللغات الأخرى، مثل:

fun read(b: Array<Byte>, off: Int = 0, len: Int = b.size) {
...
}

إذ تُعرَّف القيم الافتراضيّة باستخدام المعامِل = بعد النوع مباشرةً وتليه القيمة المطلوبة. وتعتمد التوابع (methods) التي تعيد تعريف (override) تابعٍ آخر على القيمة الافتراضيّة ذاتها للمتحولات الموجودة في التابع الأساسيّ الذي يُعاد تعريفه، حيث تُحذَف تلك القيم من ترويسة التابع الذي يعيد التعريف، كما في الشيفرة:

open class A {
    open fun foo(i: Int = 10) { ... }
}

class B : A() {
    override fun foo(i: Int) { ... }  // لا يُسمح بوجود القيم الافتراضيّة هنا
}

وإن سُبِق المتحول الوسيط الذي لا يحتوي على قيمةٍ افتراضيّةٍ بمتحولٍ وسيطٍ افتراضيٍّ فلا يُمكن حينئذٍ استخدام القيمة الافتراضيّة إلا باستدعاء الدالة بالمتحوِّل المُسمّى (named argument)، أي:

fun foo(bar: Int = 0, baz: Int) { /* ... */ }

foo(baz = 1) // ستُستخدَم هنا القيمة الافتراضية للمتحول وهي القيمة صفر

أمّا عند تمرير متحول lambda أخيرٍ في استدعاء الدالة خارج الأقواس () فيُسمَح حينئذٍ بعدم تمرير قيمةٍ للمتحولات الافتراضيّة، مثل:

fun foo(bar: Int = 0, baz: Int = 1, qux: () -> Unit) { /* ... */ }

foo(1) { println("hello") } // ستستخدم القيمة الافتراضيّة baz = 1
foo { println("hello") }    // ستستخدم القيمتين الافتراضيّتين bar = 0 , baz = 1

المتحولات المُسمّاة (Named Arguments)

تُتيح لغة Kotlin تسمية المتحوّلات الوسيطة (parameters) في الدوال عند استدعائها، وهذا يُفيد لدى وجود عددٍ كبيرٍ من المتحولات أو القيم الافتراضيّة، لتكن الدالة الآتية مثلًا:

fun reformat(str: String,
             normalizeCase: Boolean = true,
             upperCaseFirstLetter: Boolean = true,
             divideByCamelHumps: Boolean = false,
             wordSeparator: Char = ' ') {
...
}

يكون الاستدعاء باستخدام المتحولات الافتراضيّة بالشكل:

reformat(str)

وبدون المتحولات الافتراضيّة سيكون الاستدعاء بالشكل:

reformat(str, true, true, false, '_')

أمّا باستخدام المتحولات المُسمَّاة فستصبح الشيفرة أسهل للقراءة، مثل:

reformat(str,
    normalizeCase = true,
    upperCaseFirstLetter = true,
    divideByCamelHumps = false,
    wordSeparator = '_'
)

وعند عدم الحاجة لكل المتحولات يكون الاستدعاء بالشكل:

reformat(str, wordSeparator = '_')

وعند استدعاء الدالة بكلٍّ من المتحولات المُسمَّاة والوسيطة المكانيّة (positional) فيجب أن تُوضَع كافّة المتحولات المكانيّة قبل أوّل متحولٍ مُسمّى، أي أنّ الاستدعاء f(1, y = 2)‎ يكون مسموحًا، ولا يُسمح بالاستدعاء f(x = 1, 2)‎. كما يمكن تمرير عددٍ متغيّرٍ من المتحولات (vararg) بالصيغة المُسمّاة، وذلك باستخدام معامل الفصل (إسباق المصفوفة بالمعامل *) كما في الشيفرة:

fun foo(vararg strings: String) { /* ... */ }

foo(strings = *arrayOf("a", "b", "c"))

لاحظ بأن صيغة المتحولات المُسمّاة لا تُستخدَم عند استدعاء الدوال في Java، وذلك لأنّ الشيفرة bytecode في Java لا تحافظ دائمًا على أسماء المتحولات الوسيطة للدوال.

مصادر