مساحة اعلانية

آخر المواضيع

تعلم Swift من الصفر: مقدمة عن الدوال

تعلم Swift من الصفر: مقدمة عن الدوال
تعلم Swift من الصفر: مقدمة عن الدوال

من أجل إنجاز أي شيء في Swift، يجب عليك أن تتعلم الداخل والخارج من الدوال. تعد الدوال قوية ومرنة بشكل استثنائي في Swift. القواعد الأساسية بسيطة — خاصة إذا كنت قد عملت مع لغات برمجة من قبل — ولكن بسبب مرونة تركيبة كود Swift فإنها يمكن أن تصبح معقدة بكل سهولة إذا لم تكن على دراية بكل الأساسيات.
في هذا الدرس، سنركز على القواعد الأساسية أولاً وسنستطلع تركيبات الكود الأكثر تعقيداً وسنستخدم الأصناف في الدرس القادم. من المهم ألا تمر مرور الكرام على هذه القواعد الأساسية ذلك لأنهم في غاية الأهمية لفهم من أين تأتي قوة الدالة في. Swift دعونا نبدأ بمثال لنفحص بدقة بنية الدالة في Swift.

1. تعلم من خلال المثال

ما الدالة إلا كتلة من الكودات التي يمكن تطبيقها في أي وقت يحتاج لها. أرغب أن ابدأ بمثال لفحص بنية الدالة في Swift. أطلق Xcode وأنشئ ملعباً جديداً. أضف الدالة التالية لتعريف الملعب.
   
func printHelloWorld() {

    println("Hello World!")

}


تبدأ الدالة بالكلمة الأساسية func ويتبع باسم الدالة، وهو printHelloWorld في المثال، وكما هو الحال في الكثير من اللغات، فإن اسم الدالة يتبع بزوج من الأقواس على شكل هلال واللذان يحويان معاملات الدالة، مدخلات الدالة.

يلف محتوى الدالة بزوج من الأقواس المعوجة. تحتوي الدالة printHelloWorld على تصريح واحد والذي نطبع بداخله النص مرحباً أيها العالم (!Hello World) في الناتج القياسي. هذا ما ستبدو عليه الدالة الأساسية في Swift. تعتبر تركيبة الكود بسيطة، نظيفة و مختصرة.

بإمكانك استدعاء الدالة من خلال طباعة اسم الدالة، متبعاً إياها بزوج من الأقواس.
   
printHelloWorld()


2. المعاملات

دعونا نجعل المثال السابق أصعب بقليل من خلال إضافة معاملات لتعريف الدالة. هذا يعني ببساطة أننا سنزود الدالة بقيم مدخلة في محتوى الدالة. في المثال التالي، سنعرف الدالة printMessage، والتي تقبل معاملة واحدة، وهي رسالة، من نوع. String
   
func printMessage(message: String) {

    println(message)

}


يمكن للدالة أن تقبل معاملات متعددة أو قيم مدخلة. تلف المعاملات بزوج من الأقواس التي تتبع اسم الدالة. يتبع اسم المعاملة بنقطتين ونوع المعاملة. كما تذكر، هذا يشبه كثيراً الإعلان عن متغير أو ثابت. إنها تقول بكل بساطة أن معاملة الرسالة هي من نوع String.

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

يعد استدعاء الدالة مشابهاً إلى درجة كبيرة ما رأيناه مسبقاً. الاختلاف الوحيد هو أننا نقوم بتمرير المعاملة عند استدعاء الدالة.
   
printMessage("Hello World!")

لاحظ أن المصطلحان العوامل ومعاملات يستخدمان بشكل قابل للتبادل، إلا أنه يوجد اختلاف بسيط بينهما من حيث المعنى في Swift. في Swift، يطلق اسم العوامل على القيم التي تعين لتعريف الدوال بينما يطلق اسم المعاملات على القيم الممررة إلى الدالة التي تم استدعاؤها.

المعاملات المتعددة


كما ذكرت مسبقاً، تعد تركيبة كود الدوال مرنة جداً ولا يجب أن تتفاجأ لمعرفة أنه يمكن تمرير معاملات متعددة للدالة. في المثال الآتي، سننشئ تنوعاً على دالة printMessage والذي سيسمح لنا أن نطبع الرسالة عدة مرات.
   
func printMessage(message: String, times: Int) {

    for i in 0..<times {

        println("\(i) \(message)")

    }

}


في حين يتطابق اسم الدالة مع اسم الدالة الأصلية printMessage، فإن نوع الدالة يختلف. من الضروري جداً أن تفهم الجملة السابقة. اقرأها مرة أخرى.

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

نوع أول دالة هو (String) -> ()  بينما نوع الثانية هو (String, Int) -> (). إن اسمي كلا الدالتين نفس الآخر. لا تقلق حيال الرمز -> سيكون معناه واضحاً لك خلال عدة ثوان عندما نناقش أنواع الإرجاع.

تعرف الدالة الثانية printMessage معاملتين، رسالة من نوع String ومرات من نوع Int. يوضح هذا التعريف إحدى الميزات التي تبناها Swift من Objective-C، أسماء دوال/طرق مقروءة. بما أن اسم الدالة printMessage، فإنه من خلال قراءة أسماء معاملات الدالة، من السهل أن نفهم ما الذي يفترض على الدالة أن تفعله.

في الدالة الثانية printMessage، سننشئ عقدة داخلية من أجل طباعة مرات نص الرسالة. times سنستخدم العامل النصف المفتوح، ..<، كما رأينا مسبقاً في هذه السلسلة.

عندما نبدأ بكتابة printMessage في الملعب، يعرض Xcode كلا الدالتين في قائمة autocompletion. من السهل اختيار الدالة التي مهتمين بها ويعود الفضل بذلك إلى نوع الدالة. إن استدعاء الدالة الثانية بسيط جداً كالتالي:
   
printMessage("Hello World", 3)


القيم الافتراضية

إحدى الميزات المفضلة لدي هي القدرة على تعريف القيم الافتراضية للمعاملات. يمكن أن يبدو ذلك سخيفاً إذا كنت قد تعاملت مع لغة تستخدم هذه الخاصية منذ أمد بعيد، ولكنها رائعة بالفعل إذا كنت قد تعاملت مع C و Objective-C لعدة سنوات.

بالمختصر، يسمح Swift للمطورين بتعريف القيم الافتراضية لمعاملات الدالة. دعونا نقوم بتعريف دالة جديدة. تلك الدالة ستطبع التاريخ الحالي في شكل محدد. احرص على إضافة التصريح الداخل التالي في أعلى ملعبك لتستورد إطار عمل UIKit   
import UIKit


دعونا نقوم أولاً بتعريف دالة printDate من دون الاستفادة من القيم الافتراضية لأي من المعاملات.
   
func printDate(date: NSDate, format: String) {

    let dateFormatter = NSDateFormatter()

    dateFormatter.dateFormat = format

    println(dateFormatter.stringFromDate(date))

}


إذا لم تكن على دراية بإطار عمل الأساس ولا تفهم ما الذي يحصل في محتوى الدالة، فلا بأس بذلك. فإننا لا نركز في هذا المثال على إنشاء شكل  التاريخ. في printDate، نقوم باستخدام قيمة معاملة الشكل من أجل تشكيل قيمة التاريخ. إذا لم نقم بتمرير قيمة لمعاملة الشكل، فإن Swift سيعلمنا بالأمر من خلال إظهار أن هنالك خطأ ما.

يمكننا معالجة ذلك من خلال تعريف قيمة افتراضية لمعاملة الدالة الثانية كما هو موضح في تعريف الدالة المحدث في الأسفل.
   
func printDate(date: NSDate, format: String = "YY/MM/dd") {

    let dateFormatter = NSDateFormatter()

    dateFormatter.dateFormat = format

    println(dateFormatter.stringFromDate(date))

}


يعد تعريف القيمة الافتراضية بسيطاً كتعيين قيمة في قائمة المعاملات في تعريف الدالة. والنتيجة هي أن Swift لن يشتكي بعد الآن من وجود أية خطأ.
   
printDate(NSDate())


ما الذي سيحدث في حال لم نمرر قيمة لمعاملة الشكل؟ دعونا نجرب ذلك ونرى ما سيقوله Swift في تلك الحالة.

لأن لدى معاملة الشكل قيمة افتراضية وهي بذلك اختيارية، فإننا بحاجة لأن نمرر اسم المعاملة من أجل أخبار Swift عن أية معاملة نشير. يعد إصلاح ذلك بسيطاً جداً كما يمكنك أن ترى في الأسفل.
   
printDate(NSDate(), format: "dd/MM/YY")


لاحظ أن Apple ينصح بأن يتم وضع المعاملات مع قيمة افتراضية في نهاية قائمة المعاملات. هذه بالطبع فكرة سديدة وشائعة الاستخدام في معظم اللغات الأخرى التي تدعم المعاملات الاختيارية.

3. نوع الإرجاع

لا تعود الدوال التي رأينا حتى الآن بأي شيء لنا عندما نستدعيهم. دعونا نجعل دالة printDate أكثر فائدة من خلال إرجاع التاريخ المشكل كنص، بدلاً من طباعة التاريخ المشكل من داخل الدالة. يتطلب ذلك تغييران كما ترى في الأسفل.
   
func printDate(date: NSDate, format: String = "YY/MM/dd") -> String {

    let dateFormatter = NSDateFormatter()

    dateFormatter.dateFormat = format

    return dateFormatter.stringFromDate(date)

}


أولاً، يجب تغيير تعريف الدالة. نقوم بتعيين نوع الإرجاع String بعد قائمة المعاملات. يسبق نوع الإرجاع بالرمز -> إذا كنت قد عملت مع CoffeeScript، فإن هذا سيبدو مألوفاً لك.

بدلاً من طباعة التاريخ المشكل باستخدام دالة println، فإننا سنستخدم الكلمة الأساسية العودة من أجل إرجاع القيمة من الدالة. هذا كل ما سنحتاجه. دعونا نجرب ذلك.
   
let formattedDate = printDate(NSDate(), format: "dd/MM/YY")

println(formattedDate)


سنقوم باستدعاء الدالة printDate، سنخزن القيمة المرجعة في الثابت  formattedDate، وطباعة قيمة formattedDate في الناتج القياسي. لاحظ أنه لم يعد اسم دالة printDate يعكس ما تفعله ولذا لربما ترغب بتغييرها إلى formatDate.

لا يوجد نوع إرجاع

لا تملك الدوال الأخرى التي عرفناها في هذا الدرس نوع إرجاع. عندما لا يكون لدى الدالة نوع إرجاع، ليس من الضروري إدخال الرمز  -> في تعريف الدالة.

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

هذا مثير للإهتمام. ليس لدى Swift أية مشكلة حين قمنا بتخزين قيمة الدالة printHelloWorld المرجعة في ثابت، ولكنه سيشتكي عندما لا يمكنه أن يستنتج نوع قيمة الثابت.

ما الذي يحصل هنا؟ ترجع كل دالة في Swift قيمة، حتى إذا لم نقم بتعريف نوع الإرجاع في تعريف الدالة. عندما لا تحدد دالة ما نزع الإرجاع بوضوح، فإن الدالة تعود بشكل ضمني بفراغ ((Void، والذي يعادل حقلاً فارغاً أو () بشكل مختصر. يمكنك أن ترى ذلك في لوح ناتج الملعب كما هو موضح في الصورة التي  في الأعلى.

يمكننا التخلص من التحذيرات التي فوق من خلال الإعلان بكل وضوح عن نوع القيمة، حقلاً فارغاً. أوافقكم الرأي أنه ليس من المفيد تخزين حقلاً فارغاً في ثابت، ولكن هذا يوضح أن لدى كل دالة قيمة مرجعة.
   
let value: () = printHelloWorld()


Tuples حقل فارغ

تعد القدرة على إرجاع قيم متعددة لـ دالة من خلال إرجاع tuple ميزة أخرى من ميزات Swift. يوضح المثال التالي كيفية عمل ذلك. دعوني أكرر أنه ليس من الضروري أن تفهم كيف تقوم دالة timeComponentsForDate بعملها. إننا نركز هنا على القيمة المرجعة للدالة timeComponentsForDate، حقلاً فارغاً من ثلاثة عناصر.
   
func timeComponentsForDate(date: NSDate) -> (hour: Int, minute: Int, second: Int) {

    let dateComponents = NSCalendar.currentCalendar().components((.CalendarUnitHour | .CalendarUnitMinute | .CalendarUnitSecond), fromDate: date)

    let hour = dateComponents.hour

    let minute = dateComponents.minute

    let second = dateComponents.second

    return (hour, minute, second)

}

تقبل الدالة معاملة واحدة، نموذج NSDate، وتعود بحقل فارغ مع ثلاثة قيم مصنفة. يعد تصنيف قيم الحقل الفارغ فقط لراحة المستخدم، لذلك فمن الممكن حذف هذه التصنيفات.   
func timeComponentsForDate(date: NSDate) -> (Int, Int, Int) {

    let dateComponents = NSCalendar.currentCalendar().components((.CalendarUnitHour | .CalendarUnitMinute | .CalendarUnitSecond), fromDate: date)

    let hour = dateComponents.hour

    let minute = dateComponents.minute

    let second = dateComponents.second

    return (hour, minute, second)

}

و مع ذلك، كما يوضح المثال التالي، يعد تصنيف قيم الحقل الفارغ العائدة من الدالة مريحاً جداً ويجعل الكود أسهل ومفهوماً أكثر. 
let timeComponents = timeComponentsForDate(NSDate())



println(timeComponents.hour)

println(timeComponents.minute)

println(timeComponents.second)


أنه من الممكن أيضاً إرجاع قيمة اختيارية من دالة ما في حال كان هناك سناريوهات لا تعود بأية قيمة. يعد ذلك سهلاً كما هو الحال في تعريف نوع إرجاع الدالة كاختياري كما هو موضح في الأسفل.
   
func timeComponentsForDate(date: NSDate) -> (hour: Int, minute: Int, second: Int)? {

    let dateComponents = NSCalendar.currentCalendar().components((.CalendarUnitHour | .CalendarUnitMinute | .CalendarUnitSecond), fromDate: date)

    let hour = dateComponents.hour

    let minute = dateComponents.minute

    let second = dateComponents.second

    return (hour, minute, second)

}

الخلاصة
في هذا الدرس، قمنا بالتركيز على القواعد الأساسية للدوال في Swift. من الضروري أن تفهم تركيبة كود الدوال، لأننا سنستطلع في الدرس القادم دوال متقدمة أكثر.

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

الكــاتــب

    • مشاركة

ليست هناك تعليقات:

جميع الحقوق محفوظة لــ الشبح للمعلوميات 2019 ©