الفرق بين المراجعتين لصفحة: «Kotlin/control flow»
ط نقل الفقرة while إلى بعد for |
لا ملخص تعديل |
||
سطر 63: | سطر 63: | ||
else -> false | else -> false | ||
} | } | ||
</syntaxhighlight>ويُستعاض باستخدام <code>when</code> عن السلسلة الطويلة (chain) من الشرط <code>if-else if</code> ، وإن لم يكن هناك أي متحوّل (argument) واقعٍ بين قوسيّ <code>when</code> فإن شروط الحالات ستكون عبارة عن تعابير لها قيمة | </syntaxhighlight>ويُستعاض باستخدام <code>when</code> عن السلسلة الطويلة (chain) من الشرط <code>if-else if</code> ، وإن لم يكن هناك أي متحوّل (argument) واقعٍ بين قوسيّ <code>when</code> فإن شروط الحالات ستكون عبارة عن تعابير لها قيمة منطقيّة (boolean) وستُنفَّذ تعليمات الحالة التي تكون قيمتها الثنائية <code>true</code>، مثل:<syntaxhighlight lang="kotlin"> | ||
when { | when { | ||
x.isOdd() -> print("x is odd") | x.isOdd() -> print("x is odd") | ||
سطر 81: | سطر 81: | ||
*دالة تابعة للصنف (member function) أو دالة إضافيّة (extension function) مثل <code>iterator()</code> والتي يكون نوعها المُعاد: | *دالة تابعة للصنف (member function) أو دالة إضافيّة (extension function) مثل <code>iterator()</code> والتي يكون نوعها المُعاد: | ||
**يحتوي على دالةٍ تابعةٍ للصنف أو دالةٍ إضافيّةٍ <code>next()</code> | **يحتوي على دالةٍ تابعةٍ للصنف أو دالةٍ إضافيّةٍ <code>next()</code> | ||
**يحتوي على دالةٍ تابعةٍ للصنف أو دالةٍ إضافيّةٍ <code>hasNext()</code> والتي تعيد قيمة | **يحتوي على دالةٍ تابعةٍ للصنف أو دالةٍ إضافيّةٍ <code>hasNext()</code> والتي تعيد قيمة منطقيّة (boolean) | ||
وتُحدَّد هذه الدوال الثلاثة كمعاملات <code>operator</code>. | وتُحدَّد هذه الدوال الثلاثة كمعاملات <code>operator</code>. | ||
مراجعة 10:18، 29 مارس 2018
كما في أيّة لغة برمجة فإن لغة Kotlin تحتوي على تعابير للتحكم بالتدفق، وهي: تعبير if، وتعبير when، وحلقة for، وحلقة while. وتدعم كذلك الكلمتين المفتاحيّتَين continue
و break
المستخدَمتَين في الحلقات (راجع أوامر الرجوع والقفز returns and jump).
تعبير if
يُعدُّ الشرط if
في لغة Kotlin تعبيرًا يعيد قيمة، وبالتالي لا حاجة للصيغة condition ? then : else
لأن تعبير if
يقوم بهذا الدور كما في الشيفرة الآتية:
// الاستخدام الاعتيادي
var max = a
if (a < b) max = b
// استخدام else
var max: Int
if (a > b) {
max = a
} else {
max = b
}
// استخدام الشرط كتعبير
val max = if (a > b) a else b
إذا يمكن تجميع عدّة تعليماتٍ في أحد الفروع (block) بحيث تكون قيمة هذا الجزء هي قيمة آخر تعبيرٍ فيه، مثل:
val max = if (a > b) {
print("Choose a")
a
} else {
print("Choose b")
b
}
وعند استخدام if
باعتباره تعبيرًا بدلًا من تعليمة (أي أنّه قد يعيد قيمةً أو تُسنَد قيمته لمتحولٍ ما) فإنه يجب أن يكون لهذا التعبير حالة else
.
تعبير when
إنّ تعبير when
بديلٌ للمعامل switch
الموجود في لغات البرمجة مثل لغة C ومثيلاتها، وله الصيغة الآتية بأبسط شكلٍ ممكنٍ:
when (x) {
1 -> print("x == 1")
2 -> print("x == 2")
else -> { // لاحظ وجود block
print("x is neither 1 nor 2")
}
}
إذ تُجرَى المقارنة ما بين القيمة الواقعة بين قوسيّ when
والقيم الموجودة في كافّة الحالات وبالتسلسل الواردة فيه حتى يتحقَّق شرط التساوي بينهما في إحداها، ويكون استخدام الشرط when
إما كتعليمة (statement) أو كتعبير (expression)؛ فإذا ما استُخدِم باعتباره تعبيرًا فإن قيمته ستصبح بقيمة آخر حالة تحقَّق فيها التساوي، أما إن كان تعليمةً فلا أهمية لقيم أيّ من الحالات الموجودة، وكما هو الحال في if
يُمكن أن تُجمَّع عدة تعليمات ضمن نفس الحالة (block) وتكون قيمة هذا الجزء حينئذٍ بقيمة آخر تعبيرٍ موجودٍ فيه.
ويًحال نسق البرنامج إلى حالة else
إن لم تتحقَّق أيٌّ من الحالات السابقة، وعند استخدام شرط when
كتعبيرٍ فإن وجود حالة else
أمرٌ إجباريٌّ أو قد يكون اختياريًا إذا كان بوسع المُترجِم (compiler) التأكدُ من أنّ الحالات الموجودة مستوفيةٌ لكلّ الحالات الممكنة.
ويُلاحظ أنّه إذا تطابقت التعليمات بأكثر من حالة فيُمكن دمجُ الحالتين سويةً والفصل فيما بينهما بالفاصلة ,
مثل:
when (x) {
0, 1 -> print("x == 0 or x == 1")
else -> print("otherwise")
}
ويصلُح استخدام التعبير (expression) في حالات when بدلًا من القيم الثابتة، مثل:
when (x) {
parseInt(s) -> print("s encodes x")
else -> print("s does not encode x")
}
أو يمكن أن تكون مجالًا أو مجموعة (collection) بالاستفادة من المعامل in
أو !in
، مثل:
when (x) {
in 1..10 -> print("x is in the range")
in validNumbers -> print("x is valid")
!in 10..20 -> print("x is outside the range")
else -> print("none of the above")
}
وكذلك تُمكن الاستفادة من المُعامِل is
أو نفيه !is
مع أحد الأنواع (type)، ولا حاجة للمزيد من عمليات التحقّق للوصول إلى التوابع (methods) أو الخاصّيّات (properties) وهذا بفضل عمليات التحويل (smartcasts) ، مثل:
fun hasPrefix(x: Any) = when(x) {
is String -> x.startsWith("prefix")
else -> false
}
ويُستعاض باستخدام when
عن السلسلة الطويلة (chain) من الشرط if-else if
، وإن لم يكن هناك أي متحوّل (argument) واقعٍ بين قوسيّ when
فإن شروط الحالات ستكون عبارة عن تعابير لها قيمة منطقيّة (boolean) وستُنفَّذ تعليمات الحالة التي تكون قيمتها الثنائية true
، مثل:
when {
x.isOdd() -> print("x is odd")
x.isEven() -> print("x is even")
else -> print("x is funny")
}
تعبير for
تُستخدَم حلقة for
مع أيّ مجموعةٍ من القيم القابلة للتكرار (iterations)، وهي تماثل الحلقة foreach
في لغات البرمجة مثل C# ولحلقة for
الصيغة الآتية:
for (item in collection) print(item)
ويمكن أن تُنفَّذ عدة تعليمات (block) بالتكرار الواحد، مثل:
for (item: Int in ints) {
// ...
}
وتحتاج حلقة for
لوجود ما يجعلها تكراريّة (iterator) مثل:
- دالة تابعة للصنف (member function) أو دالة إضافيّة (extension function) مثل
iterator()
والتي يكون نوعها المُعاد:- يحتوي على دالةٍ تابعةٍ للصنف أو دالةٍ إضافيّةٍ
next()
- يحتوي على دالةٍ تابعةٍ للصنف أو دالةٍ إضافيّةٍ
hasNext()
والتي تعيد قيمة منطقيّة (boolean)
- يحتوي على دالةٍ تابعةٍ للصنف أو دالةٍ إضافيّةٍ
وتُحدَّد هذه الدوال الثلاثة كمعاملات operator
.
أمّا عند استخدام حلقة for
مع المصفوفات فتُحوَّل إلى حلقةٍ دليليّةٍ (index-based) لا تحتاج إلى إنشاء كائنٍ تكراريّ (iteration object) إذ يتمّ التكرار في الحلقة عبر الدليل (index) مثل:
for (i in array.indices) {
print(array[i])
}
أو قد تُستدعى الدالة withIndex
من المكتبة لتصبح الشيفرة بالشكل الآتي:
for ((index, value) in array.withIndex()) {
println("the element at $index is $value")
}
تعبير while
تعمل كلٌّ من حلقتيّ while
و do..while
كما في أيّة لغة برمجة أخرى، مثل:
while (x > 0) {
x--
}
do {
val y = retrieveData()
} while (y != null) // يمكن الوصول إلى المتحول هنا