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