If you’re on the path to becoming a proficient Flutter app developer, understanding the Dart programming language is your crucial first step. Dart is not just a companion; it’s the foundation upon which Flutter, the popular UI toolkit, is built. In this blog, we’ll embark on a journey through Dart’s essential concepts, from its history and basics to the advanced features that empower modern app development.
History & Introduction
Let’s start with a quick history lesson. Dart was introduced by Google in 2011 as a language designed for web development. Over time, its capabilities expanded, making it the primary language for Flutter app development. Dart combines a concise syntax with powerful features, making it a versatile choice for creating mobile, web, and desktop applications.
Basics
Environment Setup
Before diving into code, you’ll need to set up your development environment. Ensure you have Dart installed, and choose your preferred code editor.
Install Dart: First, you need to install the Dart SDK (Software Development Kit) on your computer. You can download it from the official Dart website: Dart SDK Downloads
Choose a Code Editor: You can use various code editors or IDEs for Dart development. Some popular choices include:
- Visual Studio Code (VS Code): VS Code is a popular and free code editor that has excellent Dart support through extensions.
- Install the “Dart” and “Flutter” extensions from the Visual Studio Code marketplace for a better Dart development experience.
- Android Studio with Flutter Plugin: If you plan to work with Flutter (a framework for building cross-platform mobile apps using Dart), you can use Android Studio with the Flutter plugin.
- IntelliJ IDEA with Dart Plugin: IntelliJ IDEA is another IDE that supports Dart development. Install the Dart plugin for IntelliJ IDEA.
Syntax
Dart’s syntax is clean and approachable, making it easy to learn. Its C-style structure will be familiar to many developers.
Data Types
Dart language supports the following data types −
- Numbers − It is used to represent numeric literals — Integer and Double.
- Strings − It represents a sequence of characters. String values are specified in either single or double quotes.
- Booleans − Dart uses the bool keyword to represent Boolean values — true and false.
- Lists and Maps − It is used to represent a collection of objects. A simple List can be defined as below −.
void main() {
// Creating a List of integers
List<int> numbers = [1, 2, 3, 4, 5];
// Accessing elements of the List
print("List elements:");
for (var number in numbers) {
print(number);
}
// Adding an element to the List
numbers.add(6);
// Removing an element from the List
numbers.remove(3);
print("Updated List elements:");
for (var number in numbers) {
print(number);
}
}
Output:
List elements:
1
2
3
4
5
Modified list elements:
1
2
4
5
6
Variables
Learn how to declare and use variables to store and manipulate data in your Dart programs. In Dart, you can declare variables using various data types. Here are the most commonly used data types for declaring variables in Dart:
- int: Used for integer values.
- double: Used for floating-point (decimal) values.
- String: Used for text or string values.
- bool: Used for boolean values (true or false).
- var: Dart can automatically infer the data type based on the assigned value.
Operators
Explore Dart’s operators, from basic arithmetic to logical operators for decision-making.
Arithmetic Operators: +
-
*
/
%
Assignment Operators: =
+=
-=
*=
/=
Comparison Operators: ==
!=
<
>
<=
>=
Logical Operators: &&
||
!
Increment and Decrement Operators: ++
--
Conditional (Ternary) Operator: ? :
Type Test Operators:
is
(Checks if an object is of a specific type)as
(Type casting)
Bitwise Operators:
&
(Bitwise AND)|
(Bitwise OR)^
(Bitwise XOR)~
(Bitwise NOT)<<
(Left shift)>>
(Right shift)
Other Operators:
..
(Cascade operator)?.
(Null-aware access operator)??
(Null-aware conditional operator)[]
(Subscript operator for accessing elements in lists and maps)()
(Function call operator)~/(integer division)
(Integer division operator, Dart 2.2+)
These operators are fundamental for performing various operations in Dart programming.
Loops
Master loops like `for` and `while` to control the flow of your programs.
void main() {
for (int i = 1; i <= 5; i++) {
print(i);
}
}
This code defines a main
function and uses a for
loop to iterate from 1
to 5
, printing each number on each iteration. When you run this code, it will output: 1 2 3 4 5
Decision Making
Use `if`, `else`, and `switch` statements for making decisions in your code. A decision making block evaluates a condition before the instructions are executed. Dart supports If, If..else and switch statements.
void main() {
// Example 1: If-Else Statement
int age = 18;
if (age >= 18) {
print("You are an adult.");
} else {
print("You are not yet an adult.");
}
// Example 2: Switch Statement
String day = "Monday";
switch (day) {
case "Monday":
print("It's the start of the workweek.");
break;
case "Friday":
print("TGIF! It's Friday.");
break;
default:
print("It's a regular day.");
}
// Example 3: Conditional (Ternary) Operator
bool isRaining = true;
String weather = isRaining ? "Grab an umbrella" : "Enjoy the sunshine";
print(weather);
}
output:
You are an adult.
It's the start of the workweek.
Grab an umbrella
Lists & Maps
Discover the power of collections with Dart’s Lists and Maps, essential for managing data efficiently.
Lists in OOP with Dart:
A list is a collection of values that can be of the same or different data types. Lists in Dart are ordered, indexed, and mutable, which means you can change their contents after creation. Lists are particularly useful when you need to work with a collection of items, such as a list of numbers, strings, or objects.
class Person {
String name;
int age;
Person(this.name, this.age);
}
void main() {
List<Person> people = [
Person('Alice', 25),
Person('Bob', 30),
Person('Charlie', 35),
];
// Accessing elements in the list
print(people[0].name); // Output: Alice
// Iterating through the list
for (var person in people) {
print('${person.name} is ${person.age} years old.');
}
}Maps in OOP with Dart:
Maps in OOP with Dart:
A map is a collection of key-value pairs, where each key is unique. Maps are used when you need to associate values with specific keys and retrieve those values efficiently. In OOP, maps can be used to represent associations between objects or properties.
void main() {
Map<String, String> dictionary = {
'apple': 'a round fruit with red or green skin and crisp flesh',
'banana': 'a long, curved fruit with a soft, yellow skin',
'cherry': 'a small, round, red or black fruit with a stone inside',
};
// Accessing values in the map
print(dictionary['apple']); // Output: a round fruit with red or green skin and crisp flesh
// Iterating through the map
dictionary.forEach((word, meaning) {
print('$word: $meaning');
});
}
Functions
Learn how to create functions, pass arguments, and return values, laying the groundwork for modular code.
A
function is a group of statements that together performs a specific
task. Let us look into a simple function in Dart as shown here −
void main() {
add(3,4);
}
void add(int a,int b) {
int c;
c = a+b;
print(c);
}Parameters (Default+Named)
Parameters (Default+Named)
Dart provides flexibility with default and named parameters, streamlining function usage.
There are two types of parameters
- Required Parameters
- Optional Parameters
Required Parameters:
Here, must pass arguments for all the parameters otherwise could not be execute the function, it will return error. Example-
void main() {
showDetails("your_name", "your_address", "0777777777");
}
//Required parameters
void showDetails(String name, String address, String phnNumber) {
print("your name is $name");
print("your address is $address");
print("your phone number is $phnNumber");
}
your name is your_name
your address is your_address
your phone number is 0777777777
Exited
Optional Parameters:
Optional parameters are divided as three types
- Optional positional parameters
- Optional named parameters
- Default parameters
OOP with Dart
Dart: Embracing Object-Oriented Programming
Dart, an object-oriented programming language, fully embraces the core principles of OOP, including classes, objects, inheritance, mixins, and abstract classes. With its focus on objects as real-life entities, Dart provides a robust framework for implementing key concepts like polymorphism and data hiding. The primary aim of OOP is to simplify code and enable multitasking. Dart introduces these fundamental OOP concepts:
- Class
- Object
- Inheritance
- Polymorphism
- Interfaces
- Abstract class
Here’s a brief overview of these OOP concepts in Dart.
Class:
- In Dart, a class is a blueprint for creating objects.
- It defines the structure and behavior of objects.
- A class encapsulates data (attributes) and methods (functions) that operate on that data.
- Example in Dart:
class Person {
String name;
int age;
Person(this.name, this.age);
void sayHello() {
print('Hello, my name is $name, and I am $age years old.');
}
}
Object:
- An object is an instance of a class.
- It represents a real-world entity with attributes (properties) and behaviors (methods).
- Objects are created from classes and can be used to store and manipulate data.
- Example in Dart:
var person = Person('Alice', 25); // Creating an object
person.sayHello(); // Calling a method on the object
Inheritance:
- Inheritance is a mechanism that allows a class (subclass or derived class) to inherit properties and methods from another class (superclass or base class).
- It promotes code reuse and the creation of a hierarchy of related classes.
- Example in Dart:
class Student extends Person {
String major;
Student(String name, int age, this.major) : super(name, age);
void study() {
print('$name is studying $major.');
}
}
Polymorphism:
- Polymorphism means “many forms” and is a fundamental OOP concept.
- It allows objects of different classes to be treated as objects of a common superclass.
- Polymorphism enables code flexibility and extensibility.
- Example in Dart:
void printInfo(Person person) {
person.sayHello();
}
var person = Person('Charlie', 35);
var student = Student('Dave', 22, 'Math');
printInfo(person); // Hello, my name is Charlie, and I am 35 years old.
printInfo(student); // Hello, my name is Dave, and I am 22 years old.Interfaces:
Interfaces:
- Dart doesn’t have a specific
interface
keyword but achieves interface-like behavior through abstract classes and mixins. - Interfaces define a contract that classes must adhere to by implementing the specified methods.
- Dart’s use of interfaces is more implicit, relying on the class hierarchy.
- Example in Dart:
abstract class CanFly {
void fly();
}
class Bird implements CanFly {
void fly() {
print('Bird is flying.');
}
}
Abstract Class:
- An abstract class is a class that cannot be instantiated directly; it’s meant to be subclassed.
- It may contain abstract methods (methods without implementation) that must be implemented by its subclasses.
- Dart uses the
abstract
keyword to declare abstract classes. - Example in Dart:
abstract class Shape {
double area(); // Abstract method
}
class Circle extends Shape {
double radius;
Circle(this.radius);
double area() {
return 3.14 * radius * radius;
}
}
Intermediate Dart
Keywords
Dart
has a set of reserved keywords that serve specific purposes in the
language. These keywords are crucial for defining language constructs
and operations. For example, keywords like class
, return
, if
, and for
are used to define classes, control flow, and more.
void main() {
int age = 30;
String name = 'Alice';
if (age >= 18) {
print('$name is an adult.');
} else {
print('$name is a minor.');
}
}
Null Safety
Dart’s null safety features provide a way to prevent null reference errors, making your programs more reliable and reducing unexpected crashes. With null safety, you can declare variables as non-nullable, ensuring that they always contain a valid value or are explicitly marked as nullable.
String? nullableString = 'Hello, Dart!';
String nonNullableString = 'Hello, Dart!';
Getters & Setters
Getters and setters allow you to control access to the properties of a class. Getters provide read-only access to a property, while setters allow you to modify the property’s value while applying custom logic.
class Rectangle {
double width;
double height;
Rectangle(this.width, this.height);
double get area => width * height;
set area(double value) {
if (value > 0) {
width = value;
height = value;
}
}
}
void main() {
var rect = Rectangle(5, 4);
print('Area: ${rect.area}');
rect.area = 10;
print('Updated Area: ${rect.area}');
}
Exception Handling
Exception handling in Dart allows you to gracefully handle runtime errors and prevent application crashes. You can use try-catch blocks to catch and handle exceptions, ensuring your application remains stable even when errors occur.
void main() {
try {
int result = 10 ~/ 0; // This will throw a 'DivisionByZeroException'
print('Result: $result');
} catch (e) {
print('An error occurred: $e');
}
}
Advanced Dart
Lambdas
Lambdas in Dart provide a concise way to create anonymous functions.
- They are essential for functional programming and allow you to define functions without explicitly naming them.
- Lambdas are often used for operations like mapping, filtering, and reducing collections.
- Example:
var add = (int a, int b) => a + b;
print(add(3, 5)); // Output: 8
Higher-Order Functions
Higher-order functions are functions that take other functions as arguments or return them as results.
- They provide a powerful way to abstract and encapsulate behavior.
- Higher-order functions enable you to write more generic and reusable code.
- Example:
int operate(int a, int b, int Function(int, int) operation) {
return operation(a, b);
}
var result = operate(5, 3, (a, b) => a + b);
print(result); // Output: 8
Closures
Closures in Dart capture and retain the scope of their containing function.
- They allow functions to maintain access to variables from the surrounding scope even after that scope has exited.
- Closures are useful for preserving state and behavior in asynchronous operations.
- Example:
Function makeCounter() {
var count = 0;
return () {
count++;
print(count);
};
}
var counter = makeCounter();
counter(); // Output: 1
counter(); // Output: 2
Future
Dart’s Future class is crucial for handling asynchronous programming, allowing non-blocking operations.
- A Future represents a potential value or error that will be available at some point in the future.
- It enables you to perform tasks concurrently without blocking the main thread.
- Example:
Future<int> fetchUserData() async {
await Future.delayed(Duration(seconds: 2)); // Simulate async operation
return 42;
}
fetchUserData().then((value) {
print('User data: $value');
});
Streams
Streams in Dart are used to handle data sequences that may arrive over time, such as events or data from network requests.
- They provide an elegant way to work with asynchronous data.
- You can listen to and react to events as they occur in real-time.
- Example:
Stream<int> countStream() async* {
for (int i = 1; i <= 5; i++) {
await Future.delayed(Duration(seconds: 1));
yield i;
}
}
Learn about streams for handling data sequences that may arrive over time.
Source: https://medium.com/@dudhatkirtan/flutter-developer-learning-roadmap-unveiling-the-power-of-dart-ae1c89c4e304
0 comments:
Post a Comment