ডার্ট প্রোগ্রামিং কুইক স্টার্ট

ক্রস প্লাটফর্ম অ্যাপলিকেশন তৈরির জন্য জনপ্রিয় একটা ফ্রেমওয়ার্ক হচ্ছে ফ্লাটার। ফ্লাটার ডার্ট প্রোগ্রামিং ল্যাঙ্গুয়েজের একটি ফ্রেমওয়ার্ক। যারা মোটামুটি প্রোগ্রামিং এর সাথে পরিচিত, তাদের জন্য এই আর্টিকেল। এখানে ডার্ট প্রোগ্রামিং এর বেসিক কনসেফট গুলো নিয়ে লেখার চেষ্টা করব। যেন ফ্লাটার অ্যাপ তৈরি করা সহজ হয়।

ডার্ট প্রোগ্রাম কম্পিউটারে রান করতে চাইলে ডার্ট SDK ইন্সটল করে নিতে হবে। ভিজ্যুয়াল স্টুডিও কোডের জন্য ডার্ট এক্সটেনশন রয়েছে। তা ইন্সটল করে নিতে পারেন। তাহলে আমরা ভিজুয়াল স্টুডিও কোডে ডার্ট প্রোগ্রাম রান করতে পারব। কম্পিউটারে ফ্লাটার ইন্সটল করা থাকলে আলাদা ভাবে ডার্ট ইন্সটল করতে হবে না। ফ্লাটারে সূচনা লেখা থেকে ফ্লাটার ইন্সটল গাইডলাইন পাওয়া যাবে।

ডার্ট মডার্ণ প্রোগ্রামিং ল্যাঙ্গুয়েজ। পাইথন, সুইফট, জাভা, জাভা স্ক্রিপ্ট, সি শার্প ইত্যাদির সাথে মিল রয়েছে। অন্য কোন প্রোগ্রামিং সম্পর্কে জানা থাকলে খুব দ্রুত ডার্টও শিখে নেওয়া যাবে। জেনারেটিভ AI এর কল্যাণে এখন যে কোন একটা ল্যাঙ্গুয়েজ জানলেই যে কোন ল্যাঙ্গুয়েজে সফটওয়্যার ডেভেলপমেন্ট করা যায়। তবে একটা ল্যাঙ্গুয়েজের ফিচার গুলো জানা থাকলে কোড ডিভাগ করতে সুবিধা হয়।

প্রথম ডার্ট প্রোগ্রাম

যে কোন কোড এডিটর ওপেন করি। এরপর নিচের মত কোড লিখিঃ

main() {
  print("Hello, Dart!");
}

ফাইল কোথাও সেভ করি। যেমন আমি সেভ করলাম main.dart নামে। এবার টার্মিনাল অথবা কমান্ডলাইনে গিয়ে লিখি dart main.dart । তাহলে পরের লাইনে আমরা আউটপুট পাবো Hello, Dart!

উপরের প্রোগ্রাম লক্ষ্য করিঃ

যে কোন ডার্ট প্রোগ্রামের এন্ট্রি পয়েন্ট হচ্ছে main() ফাংশন। এখান থেকেই ডার্ট প্রোগ্রাম রান করা শুরু করে। যদি main() ফাংশন না থাকে, তাহলে প্রোগ্রাম রান হবে না।

এই মেইন ফাংশনের ভেতর আমরা যে কোন ডার্ট কোড লিখতে পারব। আবার চাইলে এর ভেতর থেকে অন্য যে কোন ফাংশন কল করতে পারব।

সাধারণত যে সব ফাংশন কোন কিছু রিটার্ন করে না, সেগুলোর আগে void লিখতে হয়। যদিও এটা অপশনাল। তাই উপরের একই কোড হয়তো আমরা অন্য কোন টিউটোরিয়ালে এভাবে দেখবঃ

void main() {
  print("Hello, Dart!");
}

ডার্ট কমান্ডলাইন প্রোগ্রাম

উপরের মত করে কোড লিখলে আমাদের প্রতিবার কমান্ডলাইন বা টার্মিনালে গিয়ে ডার্ট ফাইলটা এক্সিকিউট করতে হবে। আমরা চাইলে ডার্ট কমান্ড লাইন প্রোগ্রাম তৈরি করতে পারি। তাহলে F5 প্রেস করে সরাসরি ডার্ট প্রোগ্রাম রান করতে পারব। তার জন্য ভিজ্যুয়াল স্টুডিওতে উইন্ডোজের ক্ষেত্রে Ctrl + Shift + P অথবা ম্যাকের ক্ষেত্রে Cmd + Shift + P on Mac কমান্ড প্যালেট ওপেন করে নিব। এখানে ডার্ট সার্চ করব। এর জন্য ডার্ট এক্সটেনশন এড করা থাকতে হবে।

এরপর Dart: New Project এ ক্লিক করব। এখানে একাধিক ডার্ট প্রজেক্ট তৈরির অপশন দেখব।

আমরা সিলেক্ট করব Console Application (command line app)।

এরপর লোকেশন সেট করে অ্যাপের নাম দিব। ডার্ট প্রজেক্ট তৈরির ক্ষেত্রে সব ছোট হাতের অক্ষরে প্রজেক্টের নাম লিখতে হয়। শব্দ গুলোর মাঝে পার্থক্য বুঝানোর জন্য আন্ডার স্কোর (_) ব্যবহার কতে পারব।

এই কনসোল অ্যাপে আমাদের জন্য কিছু ডিফল্ট কোড লিখে দেওয়া আছে। আমাদের কোড লিখতে হবে bin > project_name.dart ফাইলে। এছাড়া lib ডিরেক্টরিতে সিম্পল একটা লাইব্রেরি লেখা রয়েছে। যা আবার এই মেইন ফাইলে কল করা হয়েছে। আমরা চাইলে F5 প্রেস করে এই প্রজেক্ট রান করতে পারি। প্রজেক্টের মেইন ফাইলের কোড গুলো রিপ্লেস করে নিজের মত করেও লিখতে পারি। শুধু মনে রাখতে হবে যেন মেইন ফাংশন থাকে।

ডার্ট প্রোগ্রামিং এর কোর কনসেফট

এবার আমরা ডার্টের ব্যাসিক কনসেফট গুলো দেখব।

ভেরিয়েবল ও ডাটা টাইপ

ডার্ট স্ট্যাটিক টাইপড ল্যাঙ্গুয়েজ। তবে কোন ভ্যারিয়েবলের টাইপ ইনফারেন্স সাপোর্ট করে। ভ্যারিয়েবলের টাইপ না বলে দিলেও নিজে নিজে বুঝতে নিতে পারে। যেমনঃ

 double pi = 3.14;

এখানে আমরা ভ্যারিয়বলের টাইপ বলে দিয়েছি। আবার

var name = "Dart";

এখানে ভ্যারিয়েবলের টাইপ বলে না দিলেও স্ট্রিং হিসেবে ইনফার করে নিবে।

ডার্ট ডাইনামিক টাইপ সাপোর্ট করে। ডাইনামিক টাইপ ভ্যারিয়েবলে যে কোন টাইপের ডেটা রাখা যাবে। যেমনঃ

dynamic z = 42;
z = 'hello';

কোন একটা ভ্যারিয়েবলের টাইপ জানতে পারি runtimeType এর মাধ্যমে। যেমনঃ

print(z.runtimeType);

ভ্যারিয়বলের পাশাপাশি রয়েছে কনস্টেন্ট। যার ভ্যালু পরিবর্তন হবে না, সেগুলো আমরা কনস্টেন্টে রাখতে পারি। এর জন্য final অথবা const কিওয়ার্ড ব্যবহার করতে হবে।

নিচে সব গুলো উদাহরণ এক সাথেঃ

void main() {
  var name = "Dart";
  int age = 30;
  const pi = 3.14;
  bool isAwesome = true;
  dynamic z = 42;
  z = 'hello';
  print("Hello, $name! Age: $age");
  print(z.runtimeType);
}

যেহেতু ডাইনামিক টাইপে আমরা যে কোন ডেটা টাইপের ডেটা রাখতে পারি, তখন রানটাইমে আমাদের একটা ভ্যারিয়েবলে কোন টাইপের ডেটা রয়েছে, তা যাচাই করার দরকার হতে পারে। তা আমরা যাচাই করে নিতে পারি is অপারেটরের মাধ্যমে। যেমনঃ

if (z is String) {
  print("z is a string");
}

ফাংশন

ডার্ট এ ফাংশন লেখা অন্যান্য প্রোগ্রামিং ল্যাঙ্গুয়েজের মতই। যেমনঃ

int add(int a, int b) {
  return a + b;
}

void main() {
  print(add(5, 3)); // 8
}

শর্টহ্যান্ড ফাংশন

আমরা শর্টহ্যান্ড ফাংশনও লিখতে পারি। যা ল্যামডা ফাংশন নামেও পরিচিত। যেমনঃ

int multiply(int a, int b) => a * b;

উপরের ফাংশনের পূর্ণরুপ হচ্ছেঃ

int multiply(int a, int b) {
  return a * b;
}

ডার্টের ফাংশন গুলো এক একটা অবজেক্ট। আর প্রতিটা অবজেক্টের একটা টাইপ থাকে। তাই ফাংশনের টাইপ লিখতে হয়।

ডার্টে ফাংশন ভ্যারিয়েবলে এসাইন করা যায়। আবার একটা ফাংশনকে আরেকটা ফাংশনের আর্গুমেন্ট হিসেবেও পাস করা যায়। যেমনঃ

int sum = add(5, 3); // 8
int totalSum = add(2, add(2, 5));  // 9 

অ্যানোনিমাস ফাংশন

অ্যানোনিমাস ফাংশনের কোন নাম থাকে না। অনেকটা ল্যাম্বডার মত। তবে ল্যাম্বডা ফাংশন এক লাইনে লিখতে হয়, একটা মাত্র এক্সপ্রেশন থাকে সাধারণত। অ্যানোনিমাস ফাংশনে একাধিক এক্সপ্রেশন থাকতে পারে।

void main() {
  var sum = (int a, int b) {
    return a + b;
  };
  print(sum(3, 5)); // Output: 8
}

লুপ এবং কন্ডিশন

একটা কোড কতবার ইটারেশন করব, তা আগে থেকে জানলে for লুপ ব্যবহার করতে পারি। যেমনঃ

void main() {
  for (int i = 1; i <= 5; i++) {
    print("Iteration: $i");
  }
}

কোন কালেকশনে (list, set, map) লুপ চালানোর জন্য রয়েছে for-in:

void main() {
  List<String> cars = ["Tesla", "BMW", "Toyota"];
  for (var car in cars) {
    print(car);
  }
}

কোন কালেকশনে লুপ চালানোর জন্য for-in এর পাশাপাশি forEach ও ব্যবহার করতে পারি। যেমনঃ

void main() {
  List<int> numbers = [1, 2, 3, 4, 5];
  numbers.forEach((num) {
    print(num);
  });
}

একটা কন্ডিশন যতক্ষণ পর্যন্ত সত্য হয়, তক্ষণ পর্যন্ত লুপ চালানোর জন্য while লুপ ব্যবহার করা হয়।

while লুপের উদাহরণঃ

void main() {
  int count = 1;

  while (count <= 5) {
    print("Count: $count");
    count++; // Increment count
  }
}

while লুপের মতই একটা কন্ডিশন যতক্ষণ পর্যন্ত সত্য হয়, তক্ষণ পর্যন্ত লুপ চালানোর জন্য do-while লুপ ব্যবহার করা হয়। তবে এই ক্ষেত্রে আগে লুপের বডি এক্সিকিউট করে, এরপর কন্ডিশন যাচাই করা হয়। তাই যদি কন্ডিশন সত্যি নাও হয়, তাহলেও অন্তত একবার লুপের বডি এক্সিকিউট হবে। do-while লুপের উদারহরনঃ

void main() {
  int count = 1;
  do {
    print("Count: $count");
    count++; // Increment count
  } while (count <= 5);
}

কন্ডিশন

ডার্টে নিচের কন্ডিশনাল এবং কন্ট্রোল ফ্লো সাপোর্ট করে।

  • if স্টেটমেন্ট
  • if-else স্টেটমেন্ট
  • টার্নারি অপারেটর (? :)
  • switch স্টেটমেন্ট

if স্টেটমেন্ট

void main() {
  int age = 20;

  if (age >= 18) {
    print("You are an adult.");
  }
}

if-else:

void main() {
  int age = 16;

  if (age >= 18) {
    print("You can vote.");
  } else {
    print("You cannot vote.");
  }
}

একাধিক কন্ডিশন যাচাই করা লাগলে আমরা if-else if-else ব্যবহার করতে পারি। যেমনঃ

void main() {
  int marks = 75;

  if (marks >= 90) {
    print("Grade: A");
  } else if (marks >= 80) {
    print("Grade: B");
  } else if (marks >= 70) {
    print("Grade: C");
  } else {
    print("Grade: F");
  }
}

টার্নারি অপারেটর (? :)

টার্নারি অপারেটর হচ্ছে শর্টহ্যান্ড if-else। যা এভাবে লিখতে পারিঃ

void main() {
  int age = 20;
  String message = (age >= 18) ? "Adult" : "Minor";
  print(message);
}

switch স্টেটমেন্ট

একাধিক ফিক্সড ভ্যালু যদি যাচাই করা লাগে, তাহলে switch স্টেটমেন্ট ব্যবহার করতে পারি। যেমনঃ

void main() {
  String grade = "B";

  switch (grade) {
    case "A":
      print("Excellent!");
      break;
    case "B":
      print("Good job!");
      break;
    case "C":
      print("Needs improvement.");
      break;
    default:
      print("Invalid grade.");
  }
}

স্ট্রিং ইন্টারপোলেশন

স্ট্রিং এর ভেতর ভ্যারিয়েবল বা যে কোন এক্সপ্রেশন যোগ করতে স্ট্রিং ইন্টারপোলেশন ব্যবহার করতে পারিঃ

void main() {
  String name = "Alice";
  int age = 25;

  // Using $ for single variable
  print("My name is $name and I am $age years old.");
  // Output: My name is Alice and I am 25 years old.
}

কোন এক্সপ্রেশনও ব্যবহার করতে পারিঃ

void main() {
  int a = 5;
  int b = 10;
  print("The sum of $a and $b is ${a + b}.");
  // Output: The sum of 5 and 10 is 15.
}

কালেকশন

লিস্ট

void main() {
  List<String> fruits = ["Apple", "Banana", "Cherry"];
  print(fruits); // Output: [Apple, Banana, Cherry]
}

লিস্ট মডিফাই করাঃ

void main() {
  List<int> numbers = [1, 2, 3];

  numbers.add(4); // Adds an element
  numbers.remove(2); // Removes value 2
  numbers[0] = 10; // Changes first element
  print(numbers); // Output: [10, 3, 4]
}

লিস্ট জেনারেটঃ

void main() {
  List<int> numbers = List.generate(5, (index) => (index + 1));
  print(numbers); // Output: [1, 2, 3, 4, 5]
}

নির্দিষ্ট ভ্যালু দিয়ে লিস্ট জেনারেটঃ

void main() {
  List<String> repeatedList = List.filled(5, "Hello");
  print(repeatedList); // Output: [Hello, Hello, Hello, Hello, Hello]
}

লিস্টের অপারেশন গুলোঃ

অপারেশনউদাহরণআউটপুট
আইটেম এক্সেস করাnumbers[1]2
আইটেম যোগ করাnumbers.add(6);[1,2,3,4,5,6]
নির্দিষ্ট ইনডেক্সে আইটেম যোগnumbers.insert(2, 10);[1,2,10,3,4,5,6]
আইটেম রিমুভnumbers.remove(3);[1,2,10,4,5,6]
ইনডেক্স ব্যবহার করে রিমুভnumbers.removeAt(1);[1,10,4,5,6]
টোটাল আইটেম numbers.length5
খালি কিনা যাচাইnumbers.isEmptyfalse
সর্টnumbers.sort();[1,4,5,6,10]
লিস্ট রিমুভnumbers.reversed.toList();[10,6,5,4,1]
নির্দিষ্ট আইটেম আছে কিনা দেখাnumbers.contains(4);true
লিস্ট ট্রানসফর্মnumbers.map((n) => n * 2).toList();[2, 8, 10, 12, 20]
ফিল্টার আইটেমnumbers.where((n) => n > 3).toList();[4, 5, 6]

সেট

লিস্টে একই ভ্যালু একাধিকবার রাখা যায়। সেটে শুধু মাত্র ইউনিক ভ্যালু রাখা যায়। সেট তৈরিঃ

void main() {
  Set<int> numbers = {1, 2, 3, 3, 4, 4};
  print(numbers); // Output: {1, 2, 3, 4} (duplicates removed)
}

সেট মডিফাই করাঃ

void main() {
  Set<String> cities = {"Dhaka", "New York", "London"};

  cities.add("Paris"); // Adds a new city
  cities.remove("Dhaka"); // Removes an item

  print(cities); // Output: {New York, London, Paris}
}

সেট অপারেশন

অপারেশনউদাহরণআউটপুট
আইটেম যোগnumbers.add(6);{1,2,3,4,5,6}
আইটেম রিমুভnumbers.remove(2);{1,3,4,5,6}
নির্দিষ্ট আইটেম আছে কিনা যাচাইnumbers.contains(3);true
সেট ইউনিয়ন{1, 2}.union({2, 3, 4});{1,2,3,4}
ইন্টারসেকশন {1,2,3}.intersection({2,3,4});{2,3}
ডিফারেন্স{1,2,3}.difference({2,3,4});{1}

ম্যাপ (Key-Value Pairs)

ম্যাপ অন্যান্য প্রোগ্রামিঙ্গে ডিকশনারি নামে পরিচিত। যেখানে আমরা কী-ভ্যালু পেয়ারে ডেটা রাখতে পারি। যেমনঃ

void main() {
  Map<String, int> studentScores = {
    "Alice": 90,
    "Bob": 85,
    "Charlie": 88
  };
  print(studentScores); // Output: {Alice: 90, Bob: 85, Charlie: 88}
}

ম্যাপ এক্সেস এবং মডিফাই করাঃ

void main() {
  Map<String, String> countries = {
    "BD": "Bangladesh",
    "US": "United States",
    "UK": "United Kingdom"
  };
  print(countries["BD"]); // Output: Bangladesh
  countries["IN"] = "India"; // Adding a new key-value pair
  countries.remove("UK"); // Removing an entry
  print(countries); // Output: {BD: Bangladesh, US: United States, IN: India}
}

ম্যাপ অপারেশন

অপারেশন গুলোর জন্য নিচের ম্যাপ ব্যবহার করা হয়েছেঃ

Map<String, int> scores = {"Alice": 90, "Bob": 85};
অপারেশনউদাহরণআউটপুট
নির্দিষ্ট কী এর ভ্যালুscores["Alice"]90
নতুন পেয়ার যোগscores["Charlie"] = 88;{"Alice":90, "Bob":85, "Charlie":88}
আপডেট ভ্যালুscores["Alice"] = 95;{"Alice":95, "Bob":85, "Charlie":88}
একটা নির্দিষ্ট পেয়ার রুমুভscores.remove("Bob");{"Alice":95, "Charlie":88}
একটা নির্দিষ্ট কী আছে কিনা যাচাইscores.containsKey("Alice");true
ভ্যালু যাচাই করাscores.containsValue(85);true
ম্যাপের কী গুলোর লিস্টscores.keys.toList();["Alice", "Charlie"]
ম্যাপের ভ্যালু গুলোর লিস্টscores.values.toList();[95, 88]
ম্যাপ ইটারেশনscores.forEach((k,v) => print("$k: $v"));Alice: 95
Charlie: 88

ক্লাস এবং অবজেক্ট

Dart একটি Object-Oriented Language, তাই ক্লাস এবং অবজেক্ট সাপোর্ট করে। এখানে সংক্ষেপে আলোচনা করা হচ্ছে।

class Person {
  // Properties (Instance Variables)
  String name;
  int age;

  // Constructor
  Person(this.name, this.age);

  // Method
  void displayInfo() {
    print("Name: $name, Age: $age");
  }
}

void main() {
  // Creating an object of Person class
  Person p1 = Person("Alice", 25);

  // Calling method
  p1.displayInfo(); // Output: Name: Alice, Age: 25
}
  • এখানে Person নামক ক্লাসে দুইটা প্রোপার্টিজ রয়েছে, name এবং age নামে।
  • কনস্ট্রাক্টরের কাজ হচ্ছে এই ভ্যালু গুলো ইনিশিয়ালাইজ করা।
  • এখানে displayInfo() হচ্ছে এই Person ক্লাসের একটা মেথড। যা কল করলে ক্লাসের তথ্য গুলো দেখাবে।
  • p1 হচ্ছে Person ক্লাসের একটা অবজেক্ট। যা তৈরি করার সময় ক্লাসের প্রোপার্টিজ গুলো দিতে হয়েছে।

get এবং set:

একটা ক্লাসের প্রাইভেট প্রোপার্টি গুলো এক্সেস করার জন্য গেটার এবং সেটার ব্যবহার করা হয়। যা মূলত এনক্যাপসুলেশনের জন্য ব্যবহৃত হয়।

class BankAccount {
  double _balance = 0;

  // Getter
  double get balance => _balance;

  // Setter
  set deposit(double amount) {
    if (amount > 0) {
      _balance += amount;
    }
  }
}

void main() {
  BankAccount account = BankAccount();

  account.deposit = 1000; // Using setter
  print(account.balance); // Output: 1000
}

ফিউচার (Asynchronous Programming)

কোন ফাংশনের আগে Future কিওয়ার্ড ব্যবহার করে বুঝানো হয় এটি অ্যাসিঙ্ক্রোনাস ফাংশন। Dart এ async/await ব্যবহার করে অ্যাসিনক্রোনাস অপারেশন করা যায়।

Future<String> fetchData() async {
  await Future.delayed(Duration(seconds: 2));
  return "Data loaded!";
}
void main() async {
  print("Fetching data...");
  String data = await fetchData();
  print(data);
}

নাল সেফটি (? এবং !)

যা নাল রিলেটেড এরর এড়ানোর জন্য রয়েছে নাল সেফটি। যে সব ভ্যালু নাল হতে পারে, সেখানে আমরা ?? অপারেটর ব্যবহার করে ডিফল্ট ভ্যালু দিতে পারি।

void main() {
String? name;  // Nullable type
name = "Dart";
print(name!); 
name = null;
print(name ?? "Unknown"); // providing default value 
}

Null-Coalescing Assignment (??=)

কোন একটা ভ্যারিয়েবল কেবল মাত্র নাল হলেই ডেটা এসাইন করার জন্য নাল কোলেসিং এসাইনমেন্ট ( ??= ) অপারেটর ব্যবহার করা হয়ঃ

void main() {
  String? name;
  
  // Assign default value only if name is null
  name ??= "Unknown";

  print(name); // Output: Unknown
}

জেনেরিকস

রিইউজেবল কোড লেখার জন্য জেনেরিকস ব্যবহার করা হয়। ফাংশন এবং ক্লাস, দুই ভাবেই আমরা জেনেরিকস ব্যবহার করতে পারি। জেনেরিকস ফাংশন এবং ক্লাস টাইপ ইনডিপেন্ডেন্ট হয়। যে কোন টাইপের ডেটার ক্ষেত্রেই এই ধরণের ফাংশন বা ক্লাস ব্যবহার করা যায়।

জেনেরিক ক্লাসঃ

class Box<T> {
  T value;
  Box(this.value);
}

void main() {
  var intBox = Box<int>(10);
  var stringBox = Box<String>("Hello");

  print(intBox.value);  // 10
  print(stringBox.value);  // Hello
}

জেনেরিক ফাংশনঃ

T firstElement<T>(List<T> list) {
  return list.first;
}

void main() {
  print(firstElement<int>([1, 2, 3]));  // 1
  print(firstElement<String>(["A", "B"]));  // A
}

স্ট্রিম (Streams)

রিয়েল টাইম ডেটা প্রসেস করার জন্য স্ট্রিম ব্যবহার করা হয়। যেমনঃ

Stream<int> numberStream() async* {
  for (int i = 1; i <= 5; i++) {
    await Future.delayed(Duration(seconds: 1));
    yield i;
  }
}

void main() async {
  await for (var number in numberStream()) {
    print(number);
  }
}

আইসোলেট (Isolates – Multi-threading in Dart)

প্যারালাল প্রসেসিং এর জন্য আইসোলেট ব্যবহার করা হয়।

import 'dart:isolate';

void heavyTask(SendPort sendPort) {
  int sum = 0;
  for (int i = 0; i < 1000000000; i++) {
    sum += i;
  }
  sendPort.send(sum);
}

void main() async {
  ReceivePort receivePort = ReceivePort();
  await Isolate.spawn(heavyTask, receivePort.sendPort);

  receivePort.listen((message) {
    print("Received: $message");
  });
}

এনাম

ফিক্সড ডেটা সেটের জন্য এনাম ব্যবহার করা হয়।

enum Status { pending, approved, rejected }

void main() {
  Status orderStatus = Status.approved;

  if (orderStatus == Status.approved) {
    print("Order Approved!");
  }
}

Leave a Comment