تعلّم البرمجة بلغة كوتلن (14): كتلة التعبير الشرطي if

تعلّم البرمجة بلغة كوتلن (14): كتلة التعبير الشرطي if
أستمع الى المقال

تحدثنا في الدروس السابقة عن المتغيرات والقيم، وأنواع البيانات والدوال في كوتلن. في هذا الدرس، سنستعرض إحدى أهم كتل التحكم في سير تنفيذ شفرة كوتلن، ألا وهي كتلة if وتوابعها.

التعبير Expression والجملة البرمجية Statement:

عكس الكثير من لغات البرمجة، مثل: جافا وغيرها، تعتبر كتلة if في لغة كوتلن، تعبير Expression وليس جملة برمجية Statement. الفرق الرئيسي بين الاثنين، هو أن التعبير يعود بقيمة يمكن إسنادها إلى متغير مثلًا، بينما الجملة البرمجية تؤدي عملها فقط ولا تعود لنا بقيمة معينة.

كمثال على التعبير والجملة البرمجية لدينا الشفرة التالية من درس الدوال:

تعتبر الأسطر الثلاث الأولى Statement. لأنها عبارة عن إسناد للقيمة العائدة من الدالة ()sum إلى المتغيرات. لأننا إذا وضعنا أحد هذه الأسطر في دالة الطباعة ()println، لن يتم طباعة أي شيء لأنه لايوجد قيمة ليتم طباعتها بل عملية إسناد لا تعود بقيمة.

ولكن دالة ()sum نفسها عبارة عن تعبير يعود بقيمة. لذلك استطعنا إسناد قيمتها العائدة إلى المتغيرات الثلاث. وكذلك كل الدوال من المكتبة القياسية في كوتلن تعيد قيمة من نوع بيانات معين. لذلك تعتبر الأسطر الثلاث عبارة عن تعبير Expression. فدالة ()println ودالة ()print من مكتبة كوتلن القياسية، تعيدان القيمة من نوع بيات خاص يسمى Unit.

سنتحدث بتفصيل أكبر عن الفرق بين هذين المصطلحين، في درس التعبير Expression والجملة Statement.

ما هي كتلة التعبير الشرطي if:

التعبير الشرطي if، بالإنجليزية if expression، هو تعبير منطقي يقوم بإجراء حسابات منطقية مقيدة بقيمة الشرط المنطقي، صحيح true أو خطأ false. هذا يعني، إذا كان التعبير المنطقي الذي نضعه بين قوسي if صحيح منطقيًا true، افعل كذا، أو إذا خطأ منطقيًا false، افعل العكس أو لا تفعل شيئًا.

تعتمد هذه التعبيرات المنطقية، رموز مثل: أكبر من < أو أصغر من > ورمز المساواة == وغيرها من العوامل العلائقية. بالإضافة إلى كلمتي true و false اللتين يمكن إسنادها إلى متغير، كما سنرى في هذا الدرس.

قائمة العوامل العلائقية في كوتلن:

تُستخدم العوامل العلائقية Relational Operators، للمقارنة بين قيمتي عنصرين. في كوتلن لدينا ستة من هذه العوامل:

  1. عامل التساوي (==): تكون نتيجة المقارنة true إذا كان العنصر الذي على يسار العامل يساوي العنصر على يمينه. و false إذا كان العنصران غير متساويين. مثلًا إذا كانت المقارنة بين رقمين: 9 == 9، النتيجة true، أما 9 == 8 فالنتيجة false.
  2. عامل عدم التساوي (=!): تكون النتيجة true إذا لم يتساوى العنصران، و false إذا تساويا.
  3. عامل أصغر من (>): تكون النتيجة true إذا كان العنصر على يسار العامل أصغر قيمة عددية من العنصر على يمينه. و false إذا كان العنصر على اليسار أكبر.
  4. عامل أصغر من أو يساوي (=>): تكون النتيجة true إذا كان العنصر على يسار العامل أصغر قيمة عددية من العنصر على يمينه أو يساويه في القيمة. و false إذا كان العنصر على اليسار أكبر.
  5. عامل أكبر من (<): تكون النتيجة true إذا كان العنصر على يسار العامل أكبر قيمة عددية من العنصر على يمينه. و false إذا كان العنصر على اليسار أصغر.
  6. عامل أكبر من أو يساوي (=<): تكون النتيجة true إذا كان العنصر على يسار العامل أكبر قيمة عددية من العنصر على يمينه أو يساويه في القيمة. و false إذا كان العنصر على اليسار أصغر.

نقوم بإجراء المقارنة بين عنصرين لاستخدام نتيجة المقارنة في التعبير الشرطي. وتكون نتيجة المقارنة دائمًا true أو false. غض النظر عن نوع العناصر التي تشملها المقارنة إذا كانت أرقام أو نوع آخر. ولكن بالطبع يمكننا استخدام الكلمتين true و false مباشرة في التعبير الشرطي بوضعهما في متغير.

كتلة if مفردة:

أبسط صورة للكتلة البرمجية التي تبدأ بالكلمة المفتاحية if، تكون كالتالي:

نكتب كلمة if يتبعها قوسين ( ) بداخلهما نضع الشرط. سيعمل المترجم Compiler على تنفيذ الشرط داخل الأقواس بعد كلمة if أولًا، إذا كانت نتيجة الشرط صحيحة true سيذهب وينفذ الشفرة داخل الأقواس المعقوفة { }، أما كانت نتيجة الشرط خطأ false، سيتجاهل الشفرة داخل الأقواس المعقوفة.

كمثال عملي، إذا كان لدينا كتلة برمجية نريدها فقط أن يتم تنفيذها إذا الرقم 3 == الرقم 5، فسنقوم بالتالي:

سيتجاهل المترجم دالة ()println الأولى ولن يطبع جملة “ثلاثة تساوي خمسة”، ويذهب مباشرة إلى السطر خارج أقواس if المعقوفة ويطبع لنا جملة “نهاية البرنامج”. والسبب أن مترجم كوتلن أجرى حسابًا منطقيًا وعرف أن الرقم 3 لا يساوي الرقم 5، لذا النتيجة false. وإذا كانت نتيجة الشرط في if تساوي false فسيتم دائمًا تجاهل ما يأتي بعدها أو في أقواسها.

كتلة if وكتلة else:

في المثال أعلاه طبع البرنامج جملة “نهاية البرنامج”. لأننا لم نطلب منه أن يقوم بفعل شيء آخر إذا كان الشرط خطأ أو يساوي false. يمكننا إضافة كتلة أخرى لطباعة النتيجة المعاكسة، كالتالي:

أضفنا الكلمة المفتاحية else ومعها قوسيها المعقوفين { }. وبداخلهما الشفرة التي نريد من البرنامج طباعتها، في حالة لم يتم تنفيذ الشفرة داخل كتلة if. هذه المرة، سيطبع البرنامج جملة “ثلاثة لا تساوي خمسة” ثم الجملة الأخيرة “نهاية البرنامج”.

من هنا نعرف، أن if و else متعاكستين تمامًا. لن يتم تنفيذ الشفرات بداخلهما معًا في نفس الوقت نهائيًا. إما يتم تنفيذ الشفرة داخل كتلة if أو الشفرة داخل كتلة else.

برنامج لمعرفة نوع العدد الصحيح:

كمثال إذا كان لدينا متغير يحمل عددًا صحيحًا Int وليكن اسمه num. ونريد أن نتحقق من أن العدد الذي تم إسناده للمتغير num، هل هو عدد زوجي أو فردي، كالتالي:

وضعنا شرط للتحقق من كون العدد الصحيح زوجي عبر عملية القسمة بباقي، باستخدام العلامة (%)، num % 2 == 0. فنحن نعرف من الرياضيات، أنه حين قسمة أي عدد صحيح على الرقم 2 وكان باقي القسمة صفر، فهو يعتبر عدد زوجي. أما إذا كان باقي القسمة الرقم 1 فهذا يعني أن العدد فردي.

ما سيفعله المترجم هو أنه سيقسم العدد الصحيح الذي يُمثله المتغير على الرقم 2. فإذا تبقى من العدد بعد إجراء القسمة، الرقم صفر، هنا أصبح الشرط متحققًا أي true وسيدخل إلى كتلة if وينفذ الشفرة داخلها. أما إذا كان الباقي بعد القسمة رقم آخر غير الرقم صفر، فسيذهب وينفذ مباشرة ما يوجد داخل كتلة else، لأن شرط العدد الزوجي لم يتحقق.

بناءً على ذلك، إذا أسندنا إلى المتغير num العدد 10 ، سيطبع البرنامج “عدد زوجي”. أما إذا أسندنا إليه العدد 11 ، فسيطبع “عدد فردي”.

كتلة if وكتلة else if:

للتحكم أكثر في برنامجنا يمكننا وضع شروط إضافية. لفعل ذلك، نستخدم كتلة else if. فإذا أردنا التأكد أكثر من البرنامج سيطبع جملة “عدد فردي”، بالضبط حينما يقوم المترجم بإجراء عملية حسابية، ويجد أن العدد فردي فعليًا وليس لأن شرط العدد الزوجي لم يتحقق. يمكننا التعديل على الشفرة كالتالي:

وضعنا كتلة else if والتي لابد أن تأتي بعد كتلة if وليس قبلها، وأيضًا تحتاج لأن نضع لها أقواس لنضع بها الشرط. ما سيحدث هو أن البرنامج سينظر إلى شرط الـ if، إذا كان true، سيطبع “عدد زوجي” وينتهي البرنامج. أما إذا كان شرط الـ if يساوي false، يذهب إلى الكتلة التالية وينظر إلى شرطها أيضًا, إذا كان true، يطبع “عدد فردي”، أما إذا كان false فلن يطبع شيئًا.

كان يمكننا وضع كتلة else ليتم تنفيذها في حالة عدم تحقق الشرطين، ولكن كما نعرف أن العدد الصحيح يمكن أن يكون زوجي أو فردي فقط، بالتالي نحن متأكدين من أنه سيتم تنفيذ إحدى الكتلتين. لذا، يمكننا حذف كتلة else لأنه لن يتم تنفيذها أبدًا في هذه الحالة.

كتل if المتداخلة Nested if‘s:

يمكن كتابة كتلة if و كتلة else داخل كتلة if أخرى. كمثال، إذا كان لدينا متغير يُمثل عمر شخص ما، وأردنا التحقق من عمر هذا الشخص، لنضع له تعريف مناسب، يمكننا القيام بذلك عبر كتل if متداخلة، كالتالي:

للوهلة الأولى، قد يبدو البرنامج معقدًا نوعًا ما، ولكن تعالوا نشّرح الشفرة سوية لنفهم ما يحدث. لدينا كتلتي if و else خارجيتين. وداخل كتلة الـ if الخارجية هذه، لدينا ثلاث كتل داخلية، وهي: كتلة if وكتلة else if وكتلة else. كتلة else if الداخلية بها أيضًا، كتلة if خاصة بها.

في كتلة if الخارجية يتحقق البرنامج ما إذا كان المتغير age يحمل رقم أكبر من الصفر، إذا كانت النتيجة false فسيذهب مباشرة إلى كتلة else الخارجية في نهاية الشفرة ويطبع الجملة “عمر الشخص غير صحيح”. أما إذا كانت نتيجة التحقق صحيحة true، فسيدخل إلى الشفرة داخل كتلة الـ if الخارجية.

سيجد أن هناك if أخرى ولديها شرط يقول أن قيمة age أصغر من (>) 18. إذا كانت نتيجة الشرط true، سيطبع “شخص صغير العمر” وينتهي البرنامج. أما إذا كانت النتيجة false، فسيذهب إلى كتلة else if التالية.

في كتلة else if هناك شرط يقول بأن يكون متغير age أكبر من أو يساوي (=<) 18. إذا كانت النتيجة false، سيذهب إلى كتلة else الداخلية، ويطبع “شخص كبير العمر”. أما إذا كانت النتيجة true، سينتقل إلى داخل كتلة الـ else if هذه، ليجد if أخرى ولديها شرط يقول أن يكون عمر الشخص أصغر من أو يساوي (=>) 45. إذا كانت النتيجة true، سيطبع “شخص متوسط العمر”، أما إذا كانت النتيجة false، فلن يطبع شيئًا وسينتهي البرنامج. لماذا؟ لأننا لم نضع كتلة else لكتلة if التي توجد داخل كتلة else if.

بالرغم من أن فهم كتل if ضروري ونستخدمها كثيرًا في برامجنا، ولكن هذه الكتل المتداخلة قد تصبح أطول وبالتالي تعقد البرنامج ويصبح أقل قابلية للقراءة. لدينا في كوتلن كتلة أخرى تريحنا كثيرًا من هذا التعقيد، ألا وهي كتلة when، والتي سنتحدث عنها لاحقًا في هذه السلسلة.

العوامل && أو and و || أو or:

هذا العامل &&، يدمج بين شرطين يجب أن تكون قيمة كل منهما true. والعامل ||، يدمج بين شرطين يكفي أن تكون قيمة أحدهما true. وكما رأينا في مثالنا السابق، أن هناك مشكلة في كتلة if داخل كتلة else if الداخلية. باستخدام العامل &&، يمكننا دمج الشرطين والتخلص من كتلة الـ if غير الضرورية، كالتالي:

لطباعة جملة “شخص متوسط العمر”، يجب أن يتحقق شرطين في المتغير age. سيتم التحقق من الشرطين في ذات الوقت هذه المرة. إذا كانت أيًا منهما false، لن يتم طباعة العبارة السابقة، وسيتم تنفيذ الشفرة داخل كتلة else الداخلية.

المتغيرات المنطقية Booleans والعامل (!) Not:

يمكننا تقييد تنفيذ الشفرة داخل كتلة if، بقيمة متغير ذا قيمة منطقية Boolean. فإذا كان لدينا متغير يحمل القيمة true، وأردنا أن يتم تنفيذ الشفرة إذا كانت قيمة المتغير هي العكس false، سنستخدم العامل (!) Not، كالتالي:

في كتلة if الأولى وضعنا شرط أن تكون قيمة x هي true، وهذا غير صحيح لأن قيمة المتغير x هي false. لذا سيذهب إلى كتلة else if التالية ليجد أن الشرط هو عكس قيمة x والتي هي بالطبع القيمة true. أصبح الشرط متحققًا ويحمل القيمة true لذا سيدخل إلى شفرة else if وينفذها، ليطبع لنا: X is False.

هذا حدث لأن العامل (!) يعكس القيمة التي على يمينه. ولأن كتلة if ستنفذ فقط إذا كان الشرط true، لذا تم تنفيذ الكتلة الثانية، لأن عكس القيمة false التي يُمثلها المتغير x، هي القيمة true.

كتلة if كتعبير يعود بقيمة:

كما قلنا في بداية هذا الدرس، أن كتلة if في كوتلن يمكن أن تعود لنا بقيمة. ليتضح الأمر، فلننظر إلى المثال التالي:

أعلنا عن متغيرين، وأسندنا لهما قيم مختلفة. ثم أعلنا عن متغير ثالث، لنحفظ به القيمة الأكبر من المتغيرين أعلاه. لإيجاد القيمة الأكبر، استخدمنا كتلة if والتي ستعمل على تطبيق الشرط، فإذا كان قيمة المتغير a أكبر من قيمة المتغير b، فسيتم حفظ قيمة a في المتغير max، وإلا سيتم حفظ قيمة المتغير b في المتغير max.

وبما أن الشفرة في كتلة if عبارة عن سطر واحد، يمكننا التخلص من الأقواس المعقوفة لتصبح الشفرة أقصر، كالتالي:

كفائدة إضافية، تسمح لنا كوتلن بوضع كتلة if داخل دالة الطباعة ()println لطباعة القيمة الأكبر مباشرةً والتخلص من المتغير max، كالتالي:

وأخيراً علينا أن نعرف بأنه إذا استخدمنا كتلة if كتعبير يعود بقيمة، لابد أن يكون معها كتلة else وإلا سيحدث خطأ.

هذا الدرس هو جزء من سلسلة تعليم مبادئ البرمجة بلغة كوتلن. لمُتابعة الدروس منذ البداية ومُشاهدة فهرس المحتويات يمكنك الانتقال إلى الدرس الأول من هنا.

هل أعجبك المحتوى وتريد المزيد منه يصل إلى صندوق بريدك الإلكتروني بشكلٍ دوري؟
انضم إلى قائمة من يقدّرون محتوى إكسڤار واشترك بنشرتنا البريدية.