تخطَّ إلى المحتوى

الدوال في Dart: المعاملات المسماة والسهمية

الدرس 5 من 14 · Dart

الدالة مجموعة أوامر لها اسم، تكتبها مرة وتستدعيها كلما احتجتها. وفي Dart للدوال أهمية خاصة: كل شيء في Flutter تقريباً يُبنى بدوال، وكل زر يستقبل دالة تُنفَّذ عند الضغط عليه. وستلاحظ في هذا الدرس أن طريقة Flutter في كتابة الـ Widgets تعتمد على ميزة اسمها المعاملات المسماة.

void greet() {
print('أهلاً بك في Dart!');
}
int add(int a, int b) {
return a + b;
}
void main() {
greet();
print(add(3, 4));
}
الناتج
أهلاً بك في Dart!
7
  • الكلمة قبل اسم الدالة هي نوع القيمة المرجعة: int تُرجع رقماً، و void تعني «لا تُرجع شيئاً».
  • بين القوسين المعاملات بأنواعها: int a, int b.
  • return تُرجع النتيجة وتُنهي الدالة.

حتى main نفسها دالة! هي نقطة البداية التي تشغّلها Dart أولاً.

إذا كانت الدالة سطراً واحداً يُرجع قيمة، اختصرها بالسهم =>:

int square(int x) => x * x;
bool isEven(int n) => n % 2 == 0;

=> x * x تساوي تماماً { return x * x; }. ستراها في كل مكان في Flutter.

المعاملات الاختيارية بالموضع

Section titled “المعاملات الاختيارية بالموضع”

ضع المعاملات الاختيارية بين قوسين مربعين [ ]، وأعطها قيمة افتراضية أو اجعلها تقبل null:

String makeTea([int sugar = 2]) => 'شاي بـ $sugar ملاعق سكر';
String fullName(String first, [String? last]) {
if (last == null) return first;
return '$first $last';
}
void main() {
print(makeTea());
print(makeTea(0));
print(fullName('سارة'));
print(fullName('سارة', 'أحمد'));
}
الناتج
شاي بـ 2 ملاعق سكر
شاي بـ 0 ملاعق سكر
سارة
سارة أحمد

المعاملات المسماة: أسلوب Flutter

Section titled “المعاملات المسماة: أسلوب Flutter”

عندما يكثر عدد المعاملات، يصعب تذكر ترتيبها. ما معنى createUser('عمر', 15, 'جدة', true)؟ الحل: المعاملات المسماة بين قوسين معقوفين { }:

String createUser({
required String name,
required int age,
String city = 'القاهرة',
}) {
return '$name ($age سنة) من $city';
}
void main() {
print(createUser(name: 'عمر', age: 15));
print(createUser(age: 20, name: 'منى', city: 'جدة'));
}
الناتج
عمر (15 سنة) من القاهرة
منى (20 سنة) من جدة
  • عند الاستدعاء تكتب اسم كل معامل: name: 'عمر'، فيصبح الكود مقروءاً كجملة.
  • الترتيب لا يهم: لاحظ أننا كتبنا age قبل name في الاستدعاء الثاني.
  • required: هذا المعامل إجباري رغم أنه مسمى.
  • المعامل بقيمة افتراضية مثل city اختياري.

تخيّل الفرق بين أن تملأ استمارة بلا عناوين للخانات، وبين استمارة مكتوب بجانب كل خانة «الاسم» و«العمر». المعاملات المسماة هي الاستمارة الواضحة.

في Dart، الدالة قيمة مثل الأرقام والنصوص: تستطيع وضعها في متغير، وتمريرها لدالة أخرى:

int square(int x) => x * x;
int applyTwice(int Function(int) f, int x) => f(f(x));
void main() {
int Function(int) op = square;
print(op(6));
print(applyTwice(square, 2));
}
الناتج
36
16

int Function(int) هو نوع الدالة: «دالة تأخذ int وتُرجع int». و applyTwice طبّقت square مرتين: مربع 2 هو 4، ومربع 4 هو 16.

أحياناً تحتاج دالة صغيرة مرة واحدة فقط، فلا داعي لتسميتها:

var numbers = [1, 2, 3];
numbers.forEach((n) {
print(n * 10);
});
var doubled = numbers.map((n) => n * 2).toList();
print(doubled);
الناتج
10
20
30
[2, 4, 6]

(n) { ... } و (n) => n * 2 دوال بلا اسم، مررناها مباشرة. وهكذا بالضبط ستكتب في Flutter: onPressed: () { ... } لتحدد ماذا يحدث عند الضغط على زر.

اكتب دالة تحسب السعر بعد الخصم، والنسبة معامل مسمى قيمته الافتراضية 10:

double priceAfterDiscount(double price, {double percent = 10}) =>
price - price * percent / 100;
void main() {
print(priceAfterDiscount(200));
print(priceAfterDiscount(200, percent: 25));
}
الناتج المتوقع
180.0
150.0

تحدٍّ: اكتب دالة describeStudent بمعاملين مسميين إجباريين name و score، تُرجع «ناجح» أو «راسب» مع الاسم.

  • نسيان return في دالة لها نوع: المحرر يعترض، لأن الدالة وعدت بقيمة ولم تُرجعها.
  • نسيان اسم المعامل عند الاستدعاء: createUser('عمر', 15) خطأ مع المعاملات المسماة. الصحيح createUser(name: 'عمر', age: 15).
  • الخلط بين f و f(): onPressed: save تمرر الدالة لتُنفَّذ لاحقاً، أما onPressed: save() فتنفذها فوراً وتمرر نتيجتها! خطأ شائع جداً في Flutter.

سؤال

كيف تستدعي void order({required String item, int qty = 1}) لطلب 3 أقلام؟

سؤال

ما الذي يساويه int triple(int x) => x * 3;؟

  • الدالة تُعرَّف بنوع قيمتها المرجعة، و void لا تُرجع شيئاً.
  • => تختصر الدالة ذات التعبير الواحد.
  • [ ] للمعاملات الاختيارية بالموضع، و { } للمعاملات المسماة مع required والقيم الافتراضية.
  • المعاملات المسماة هي أساس شكل كود Flutter.
  • الدوال قيم: تُخزَّن في متغيرات، وتُمرر لدوال أخرى، وتُكتب مجهولة عند الحاجة.