Data Type in Dart

🧠 ما هي أنواع البيانات؟

أنواع البيانات (Data Types) تُستخدم لتحديد نوع القيمة التي يمكن تخزينها في المتغير.

Dart لغة قوية في هذا المجال وتدعم أنواعا متعددة.

✅ أنواع البيانات الأساسية في Dart:

1- النصوص (String):

ما هو الـ String في Dart؟

في Dart، النوع String يُستخدم لتمثيل سلاسل النصوص، أي مجموعة من الأحرف مثل الجمل والكلمات والأرقام كـ نص.
تُكتب السلاسل النصية عادة بين علامتي اقتباس مفردة ' ' أو مزدوجة " ".

void main() {
  String name = 'أحمد';
  String greeting = "مرحبًا بك في Dart!";
  
  print(name);       // أحمد
  print(greeting);   // مرحبًا بك في Dart!
}
Dart
🔹 إشارات التنصيص في Dart

في Dart، يمكن كتابة السلاسل النصية باستخدام:

“””نص متعدد الأسطر أيضاً”””

‘علامات تنصيص مفردة’

“علامات تنصيص مزدوجة”

”’نص متعدد الأسطر”’

🟢 القاعدة العامة:
✅ إذا كانت السلسلة تحتوي على علامات تنصيص مزدوجة داخلية، استخدم المفردة:
String text = 'قال المعلم: "البرمجة ممتعة!"';
Dart

✅ وإذا كانت تحتوي على علامات تنصيص مفردة داخلية، استخدم المزدوجة:

String text = "اسم الطالب هو 'أحمد'";
Dart
🔸 ماذا لو احتجت تكتب نفس نوع التنصيص داخل السلسلة؟

هنا نستخدم الشرطة المائلة العكسية (backslash ) للهروب من المعنى الخاص للتنصيص:

String text1 = 'قال: \'مرحبًا!\'';
String text2 = "المسار هو: C:\\Program Files\\App";
Dart
✅ مثال:

✅ دمج النصوص (String Concatenation)

void main() {
  String firstName = 'محمد';
  String lastName = 'علي';
  
  String fullName = firstName + ' ' + lastName;
  print(fullName); // محمد علي
}
Dart

✅ أو يمكنك استخدام الـ interpolation:

void main() {
  String name = 'سارة';
  int age = 22;
  
  print('اسمي $name وعمري $age سنة'); 
  // اسمي سارة وعمري 22 سنة
}
Dart

✅ السلاسل متعددة الأسطر (Multiline Strings)

void main() {
  String message = '''
  هذا نص متعدد الأسطر.
  يمكنني الكتابة في أكثر من سطر.
  مرحبًا بك!
  ''';

  print(message);
}
Dart
✅ بعض دوال String المفيدة
.lengthطول السلسلة'Dart'.length4
.toUpperCase()تحويل إلى أحرف كبيرة'dart'.toUpperCase()'DART'
.toLowerCase()تحويل إلى أحرف صغيرة'DART'.toLowerCase()'dart'
.contains()التحقق من وجود جزء في النص'hello'.contains('he')true
.replaceAll()استبدال جزء معين'Hi Ali'.replaceAll('Ali', 'Omar')
.split()تقسيم النص إلى قائمة'a,b,c'.split(',')[a, b, c]
.trim()إزالة المسافات الزائدة' hello '.trim()'hello'

أ. الأعداد (Numbers)

int – الأعداد الصحيحة

في لغة Dart، نوع البيانات int يُستخدم لتمثيل الأعداد الصحيحة، أي الأرقام التي لا تحتوي على جزء عشري. يُعتبر int جزءًا من الأنواع الرقمية في Dart.

خصائص int في Dart:

القيم الصحيحة: يستخدم لتخزين القيم العددية الصحيحة، مثل 10 أو -50 أو 1000.

النطاق: يعتمد نطاق الأعداد الصحيحة على بيئة التشغيل. في معظم أنظمة التشغيل الحديثة، يمكن أن يصل int إلى قيم كبيرة جدًا لأن Dart تستخدم تمثيل 64-bit للأعداد الصحيحة.

عمليات رياضية: يمكن تنفيذ العديد من العمليات الحسابية على القيم من النوع int، مثل الجمع، الطرح، الضرب، القسمة الصحيحة (~/)، والقسمة العادية.

void main() {
  int age = 25;            // تعريف متغير من نوع int
  int score = -10;         // يمكن أن يكون العدد سالبًا
  int bigNumber = 1000000; // أرقام كبيرة

  // العمليات الحسابية
  int sum = age + score; // الجمع
  int product = age * 2; // الضرب
  int division = age ~/ 2; // القسمة الصحيحة

  print("العمر: $age");
  print("الناتج من الجمع: $sum");
  print("الناتج من الضرب: $product");
  print("القسمة الصحيحة: $division");
}
Dart

double – الأعداد العشرية

في لغة Dart، نوع البيانات double يُستخدم لتمثيل الأعداد العشرية، أي الأرقام التي تحتوي على جزء عشري. يُعتبر double جزءًا من الأنواع الرقمية في Dart إلى جانب int الذي يُستخدم للأعداد الصحيحة

خصائص double في Dart:

  • تمثيل الأعداد العشرية: يمكنه تخزين القيم ذات الفواصل العشرية، مثل 10.5 أو -3.14.
  • دقة عالية: يُستخدم للأرقام التي تتطلب دقة أكبر من int.
  • يدعم العمليات الحسابية: مثل الجمع، الطرح، الضرب، القسمة، وغيرها.
  • **يعتمد على نظام IEEE 754 لتمثيل الأعداد العشرية في الحاسوب.

أمثلة على استخدام double:

void main() {
  double price = 99.99; // تعريف متغير من نوع double
  double pi = 3.14159;  // قيمة تقريبية للعدد π
  double negativeNum = -5.5; // عدد عشري سالب

  print("السعر: $price");
  print("قيمة π: $pi");
  print("عدد عشري سالب: $negativeNum");
}
Dart

العمليات الحسابية على double:

void main() {
  double a = 5.5;
  double b = 2.2;

  double sum = a + b; // الجمع
  double difference = a - b; // الطرح
  double product = a * b; // الضرب
  double division = a / b; // القسمة
  double rounded = a.roundToDouble(); // التقريب لأقرب عدد صحيح

  print("المجموع: $sum");
  print("الفرق: $difference");
  print("الناتج من الضرب: $product");
  print("القسمة: $division");
  print("التقريب: $rounded");
}
Dart

متى تستخدم double؟

  • عند الحاجة إلى دقة في الأعداد العشرية (مثل العمليات المالية أو الحسابية الدقيقة).
  • عندما تحتاج إلى إجراء عمليات رياضية على الأعداد العشرية مثل sqrt() أو pow().
  • عند التعامل مع القيم الصغيرة جدًا أو الكبيرة جدًا التي تحتاج إلى دقة حسابية.

دوال خاصة بـ double:

  • toInt(): تحويل double إلى int (يقوم بحذف الجزء العشري بدون تقريب).
void main() {
  double num = 9.8;
  print(num.toInt()); // 9
}
Dart
  • ceil(): التقريب للأعلى.
void main() {
  double num = 3.2;
  print(num.ceil()); // 4
}
Dart
  • floor(): التقريب للأسفل.
void main() {
  double num = 3.9;
  print(num.floor()); // 3
}
Dart
  • round(): التقريب لأقرب عدد صحيح.
void main() {
  double num = 3.5;
  print(num.round()); // 4
}
Dart

ب. القيم المنطقية (Boolean)

في Dart، القيم المنطقية (Boolean values) تُستخدم لتمثيل حالتين فقط: true (صحيح) و false (خطأ). وهي من النوع bool.

تُستخدم القيم المنطقية عادةً في عمليات المقارنة، واتخاذ القرارات، والتحكم في سير عمل البرنامج.

خصائص bool:

  • تحتوي على حالتين فقط: true أو false.
  • تُستخدم في الشروط والعمليات المنطقية مثل if, while, &&, ||, و !.
  • مفيدة جدًا للتحقق من القيم واتخاذ القرارات داخل التطبيق.

مثال:

void main() {
  bool isActive = true;
  bool isCompleted = false;

  print("هل النظام نشط؟ $isActive");   // هل النظام نشط؟ true
  print("هل المهمة مكتملة؟ $isCompleted"); // هل المهمة مكتملة؟ false
}
Dart

متى نستخدم bool:

  • عندما تحتاج إلى اتخاذ القرارات داخل التطبيق.
  • عند التحقق من شروط معينة، مثل حالة تسجيل الدخول، أو توفر البيانات.
  • عند استخدام العمليات المنطقية، مثل العمليات الحسابية أو الفلاتر في القوائم.
bool isRaining = true;
bool isLoggedIn = false;
bool hasPermission = (age >= 18);
Dart

Var:

في Dart، الكلمة المفتاحية var تُستخدم للإعلان عن متغير دون تحديد نوعه صراحةً، مما يعني أن Dart ستحدد نوع المتغير تلقائيًا بناءً على القيمة المُسندة إليه أثناء التهيئة.

خصائص var في Dart:

  1. تحديد النوع تلقائيًا: Dart تستنتج نوع المتغير من القيمة الأولية التي يُسند إليها.
  2. لا يمكن تغيير نوع المتغير بعد تعيين القيمة الأولية.
  3. يجب تعيين قيمة أولية عند استخدام var، وإلا سيكون المتغير من نوع dynamic.
void main() {
  var name = "ياسين"; // Dart تستنتج أن النوع هو String
  var age = 25; // Dart تستنتج أن النوع هو int
  var price = 99.99; // Dart تستنتج أن النوع هو double

  print(name.runtimeType); // String
  print(age.runtimeType);  // int
  print(price.runtimeType); // double
}
Dart

عدم إمكانية تغيير نوع المتغير بعد تعيينه:

void main() {
  var x = 10;  // Dart تستنتج أن x من نوع int
  // x = "Hello"; // ❌ خطأ: لا يمكن تغيير نوع المتغير إلى String
}
Dart

الفرق بين var و dynamic:

إذا لم تُسند قيمة إلى متغير var، يصبح نوعه dynamic، مما يعني أن Dart لن تحدد نوعه، ويمكن تغيير نوعه لاحقًا.

void main() {
  var something; // لم يتم تحديد النوع، يصبح `dynamic`
  print(something.runtimeType); // Null

  something = "مرحبا"; // الآن النوع String
  print(something.runtimeType); // String

  something = 100; // تغيير النوع إلى int
  print(something.runtimeType); // int
}
Dart

Dynamic

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

خصائص dynamic في Dart:

  1. يمكن أن يحتوي على أي نوع من القيم (int, double, String, bool, قائمة، كائن…).
  2. يمكن تغيير نوعه خلال تشغيل البرنامج.
  3. لا يدعم فحص النوع أثناء وقت الترجمة، مما قد يؤدي إلى أخطاء عند التنفيذ.

استخدام dynamic:

void main() {
  dynamic variable = 10;  // في البداية، النوع int
  print(variable.runtimeType); // int

  variable = "مرحبا";   // تغيير النوع إلى String
  print(variable.runtimeType); // String

  variable = true;  // تغيير النوع إلى bool
  print(variable.runtimeType); // bool
}
Dart

الفرق بين dynamic و var

النوعيحدد النوع تلقائيًا؟يمكن تغيير النوع لاحقًا؟يفحص الأخطاء أثناء الترجمة؟
var✅ نعم❌ لا✅ نعم
dynamic❌ لا✅ نعم❌ لا

var يستنتج النوع من القيمة الأولية لكنه لا يسمح بتغييره لاحقًا، بينما dynamic يقبل أي نوع ويمكن تغييره خلال التنفيذ

متى تستخدم dynamic؟

  • عندما تحتاج إلى تخزين أنواع متعددة في نفس المتغير.
  • عند التعامل مع بيانات غير محددة مسبقًا (مثل البيانات القادمة من الشبكة).
  • في الحالات التي لا يمكن فيها تحديد النوع مسبقًا.

لكن يفضل استخدام var أو تحديد النوع int, String, إلخ، عندما يكون ذلك ممكنًا، لأن dynamic قد يؤدي إلى أخطاء غير متوقعة.

كيفية معرفة نوع المتغير في لغة Dart

في لغة Dart، هناك عدة طرق لمعرفة نوع المتغير أثناء وقت التشغيل (runtime). إليك الطرق الرئيسية:

1. استخدام العامل is و is!
أ. التحقق باستخدام is

ب. التحقق باستخدام is! (ليس من النوع)

var text = 'Hello';

if (text is! int) {
  print('هذا ليس عدد صحيح');
}
Dart

2. استخدام العامل runtimeType

var variables = [
  42,
  'Hello',
  3.14,
  true,
  [1, 2, 3],
  {'name': 'Ali'}
];

for (var variable in variables) {
  print('القيمة: $variable - النوع: ${variable.runtimeType}');
}

//النتيجة
القيمة: 42 - النوع: int
القيمة: Hello - النوع: String
القيمة: 3.14 - النوع: double
القيمة: true - النوع: bool
القيمة: [1, 2, 3] - النوع: List<int>
القيمة: {name: Ali} - النوع: _InternalLinkedHashMap<String, String>
Dart

3. استخدام Type مع == للمقارنة

var number = 10;

if (number.runtimeType == int) {
  print('هذا متغير من النوع int');
}
Dart
ملاحظات مهمة
  1. runtimeType يعطي النوع الدقيق للكائن أثناء التشغيل.
  2. is و is! أكثر أماناً عند التعامل مع الفئات (classes) والوراثة.
  3. في Dart 3.0+ يمكن استخدام pattern matching مع switch للتعامل مع الأنواع بطريقة أكثر تعبيراً.
  4. عند استخدام dynamic، يجب التحقق من النوع قبل تنفيذ العمليات.

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