Dart Generator is a unique function that allows us to produce a sequence of values. Generators return values on demand; it means the value is generated when we try to iterate over the iterators. Dart provides built-in support for two types of generator functions. Synchronous Generator It returns an iterable object which carries value synchronously. The yield keyword is used along with marking the synchronous generator function body as sync* to generator values. Let’s understand the following example of a synchronous generator. Example – Output Explanation: In the above program, we declared an oddNumber(10) function with the foreach loop without its body. The foreach loop will iterate the function. Now, we created oddNumber(10) function as synchronous generator function. In the function body, we initialized a new variable k, which assigns the argument n. Then, we applied while loop to iterate the function, and the loop body is iterated until the value of k is less than or equal to 0. We did modulus operation on k to find the odd numbers from the generators. We used the yield statement, which suspends the function’s execution and returns the value at a time. It will return the value of each execution of the generator function. When the while loop’s condition becomes false, then the loop terminated and prints the odd numbers. Asynchronous Generators It returns a stream object which carries value asynchronously. The yield keyword is used along with marking the asynchronous generator function body as async* to generator values. Let’s understand the following example – Example – Output Explanation: The above code generated values asynchronously. The asyncNaturalsTo(int num) function returns a stream objects in each execution of function body. Here, the yield keyword behaved the same as the previous example; it stopped the execution of the function, returned the value, and resumed the execution for the next iteration. It will happen again and again until the function body is terminated. Let’s understand the following concepts related to the generator function. The yield Keyword The yield returns the single value to the sequence at a time but does not stop the execution of the generator function completely. It returns a value for each execution of the generator function. The sync* Keyword – The sync* keyword is used to declare the synchronize generator function. It returns the value when we try to iterator the value not when it was created. Let’s have a look at the following example – Example – Output Explanation – The above generator function generated the value when we iterate over the iterator. The async* Keyword The async keyword is used to declare the asynchronous generators. It returns the stream object. Let’s understand the following example – Example – Output
Libraries
In Dart, the library is the collection of the routine or set of programming instructions. Dart consists of many sets of built-in libraries that are beneficial to hold routines (functions, set of classes, etc.), and regularly used. A Dart library contains constants, functions, properties, exceptions, and typedefs, and set of classes. Importing a library To work with the library, we must import it into the current program. The Dart provides the import keyword, which is used to make the library available in the current file. We can use multiple libraries in a single file. For example – Dart built-in library URIs is used as dart scheme to refer to a library. Other libraries can use a file system path or the package: scheme to specify its URIs. The package manager pub in Dart provides the libraries and uses the package scheme. We are describing some commonly used libraries below. Sr. Library Description 1. dart:io This library consists of File, HTTP, socket, and other I/O support for server applications. This library is not suitable for browser-based applications. We don’t need to import explicitly because it is imported by default. 2. Dart:core This library consists of Collection, built-in types, and other core functionality for each dart program. It is imported by default. 3. Dart: math This library consists of the rich mathematical functions, constant, and random number generator. 4. Dart: convert It is used to Encoders and decoders for converting the different data representations such as JSON and UTF 5. Dart: typed_data It represents the lists that store the fixed-sized data efficiently (for example – unsigned 8-byte integer). Let’s understand the following example of importing and using a library function. Example – Importing and using a Library Output: Explanation: In the above code, we imported the built-in library ‘dart:math’. It provides the many built-in mathematical function, here we used the sqrt() function with number. It takes a number as an argument that we want to find its square root of. We passed an integer number 25 in sqrt() function, and it retuned an output as 5. Encapsulation in Libraries Dart provides the facility to encapsulate or restrict access the content of the dart library. It can be done by using the _(underscore), followed by the identifier. The _(underscore) symbol makes the library’s content completely private. The syntax is given below. Syntax: Example – We define a library called Greetings that has a private function. The above file saves as greetings.dart, now we import the library. Output: After running the above code, it throws an error because we have declared the library with the private method and try to access it in other file. Creating Custom Libraries (User-defined Library) We can also use our own code as a library and import it when needed. This type of library is called a custom library. Below are the steps to create a custom library. Step – 1: Declaring a Library The library statement is used to create a library explicitly. The syntax is given below. Syntax: Step – 2: Connecting a Library We can connect a library in two ways. Let’s understand the following example – Example – Custom Library Now we import the above custom file in current file called ‘library.dart’. Output: Copy the above code and paste it into your dart editor and observe the result. Note – The custom library must be imported by its saved file name such as we imported it in the current working file with the calculator_simple name. Name Alias of Library Dart allows us to import multiple libraries into the current working file, but if we create the same function name within the different libraries, it will create conflict while accessing these functions. The Dart compiler might be confused to identify the particular function in different library. To overcome this scenario, Dart provides the as keyword for specifying the prefix. The syntax is given below. Syntax: Let’s understand the following example – Example – First, we define a library: greeting.dart Next, we define the new library: hellogreetings.dart Now, we import the above libraries with the as prefix. Output:
Packages
Dart package is the collection of a well-organized, independent, and reusable code unit. Applications might be needed to implement third-party libraries or packages. The package generally contains a set of classes, functions, or unit of code for specific tasks along with the compiled program and sample data. Dart provides an extensive set of default packages that load automatically when the dart console starts. However, if we need packages other than the default packages then its need to installed and loaded explicitly in order to use. When a package is loaded, it can be used in the whole Dart environment. Dart Package Manager Every language provides the functionality for handling the external packages such as Nuget for .NET, Gradle or Maven for Java, npm for Node.js, etc. Dart has the inbuilt package manager, which is called a pub. It is basically used to organize, manage the third-party libraries, tools, dependencies, and also used to install the packages in the repository. Every Dart application consists of a pubspec.yaml file which includes the metadata of the file. The metadata of the package holds the author, version, application name, and description. The full form of the yaml is a Yet Another Markup Language. The pubspec.yaml is used to download the various libraries that application needs during programming. The pubspec.yaml file must look like as follows. The Dart IDE’s provides the inbuilt support for using the pub that consist of creating, downloading, updating, and publishing packages, Otherwise we can use the pub command line. The following is the list of the few important pub commands. Sr. No Description pub get It is used to get all packages of application dependent on. pub upgrade It is used to upgrade all application dependencies to the modern version. pub build It is used to construct your web application, and it will create a build folder, with all related scripts in it. pub help It is used to get help related to all pub commands or when we stuck while programming. Installing a Package The following steps are defining the installation of the package in the project. Step – 1: Write the package name in the dependencies section of project’s pubspec.yaml file. Then run the below command to find the package installed in project. The above command will download the package under the packages folder in the application directory. Example – We have added the xml to the project dependencies. Now we can use Dart XML package in the project by importing it. It can be imported as follows. Read XML String We can read XML string and authenticate the input; Dart XML provides a parse() method to read the string input. The syntax is given below. Let’s have a look at the following example: Example – Parsing XML String Input In the following example, we display the parsing XML string input. Output:
Generics
Dart Generics are the same as the Dart collections, which are used to store the homogenous data. As we discussed in the Dart features, it is an optionally typed language. By default, Dart Collections are the heterogeneous type. In other words, a single Dart collection can hold the values of several data types. However, a Dart collection can be also stored the homogenous values or same type values. The Dart Generics provides the facility to enforce a limit on the data type of the values that can be stored by the collection. These collections can be referred to as the type-safe collections. Type safety is a unique feature of the Dart programming, which makes sure that a memory block can only contain the data of a specific data type. The generics are a way to support type-safety implementation for all Dart collections. The pair of the angular bracket is used to declare the type-safe collection. The angular bracket consists of the data-types of the collection. The syntax is given below. Syntax – We can do the type-safe implementation of various Dart objects such as List, Queue, Map, and Set. It is also supported by all implementation of the above define collection types. The syntax is given below. Example – Generics List Output Explanation: We created a list that holds the string type-safe and used the add element into it by using add() function. If we try to insert the other than the specified value then it will through a compilation error. Let’s understand the following example – Example – 2 Output Let’s understand another example – Example – Generic Set Output Example – Generics Queue Output Generic Map As we know that declaring map require the key and value. The syntax is given below. Syntax: Example – Output
Collection
Dart doesn’t support the array to store the data, unlike the other programming language. We can use the Dart collection in place of array data structure. We can enable the other classes of the collection in our Dart script by using the dart::core library. Dart collection can be classified as follows. Dart Collection Description List A list is the collection of the ordered group of collection. The dart::core library offers the list class that allows us to create and modify the list. It provides the following types of lists.Fixed Length List – We cannot change the list’s length at runtime.Growable List – We can change the length of the list at run-time. Set A set is the collection of the objects in which each object can be declared at once. The dart::core library offers the Set class to use its facilities. Maps The maps are the collection of the key-value pair of data. Each value is stored with a particular key. The key and value can be any type in the dart. A Map is a dynamic collection. We can say that map can be modified at the run-time. The dart::core library makes available the Map class to work with it. Queue A queue is the collection of the where data stores in the first-in-first-out format. It can be manipulated at both ends. Simply, we can enter the element from one end and delete it from another end. Iterating Collections The dart::core library provides the iterator class, which enables the easy collection traversal. As we know that, every collection contains an iterator property. This property returns an iterator that point to the objects in the collection. Let’s understand the following example. Example – Output Explanation: In the above code, the moveNext() function returned the Boolean value that indicating whether there is a subsequent entry. The current property of the returns the object of that iterator currently points to. HashMap <K, V Class> The HashMap class is based on the implementation of the Map. As we discussed earlier, the key must be unique and must have consistent Object == (equal to operator) and Object.hashCode implementations. We can also use null as a key. The elements in the Map may in any order. The iteration order only changes if the map is modified. If we iterate the map, the value of the map is iterated in the same order as their associated key.
Typedef
In Dart, the typedef is used to generate an alias for function type that we can use it as type annotation for declaring variables and return types of that function type. An alias of function type can be used as type annotation in variable declaration or function return type. A typedef stores the type information when we assigned the function type to a variable. Declaring a typedef A typedef keyword is used to create an alias for function that will be the same as the actual functions. We can also create a function prototype with a list of parameters. The syntax is given below. Syntax: Example – Let’s create an alias of MultiOperation(int n1, int n2) that contains two parameters of the integer type. Assigning typedef Variable We can assign any function with the same parameter to the typedef variable. The syntax is given below. Syntax: Let’s understand the following example, where we define the two functions with the same signature as the MultiOperation. Calling Function with typedef We can invoke function by passing the same parameter by using the typdef variable. The syntax is given below. Syntax: Example: The mp is a typedef variable, which can be used to refer any method that accepts two integer parameters. The function reference can be switched at runtime by using the typedefs. Complete Program using typedef Let’s have a look at the following example. Output: Explanation: In the above code, we created the alias of the MultiOperation() function using the typedef keyword. We defined two more functions Sum() and Sub(), which have same signature as the typedef function. Then, we assigned the typedef variable mp that referred to both functions Sum() function and Sub() function. Now, we invoked the function by passing the required argument, and it printed the result to the screen. Typedef as Parameter We can use the typedef method as a parameter. In the following example, we are creating an additional function to the above program NumericOperaion(int n1, int n2, MultiOperation mp) with the two integer variables and typedef ManyOperation mp as its parameter. Example – Output: In the above code, we didn’t need to create a typedef variable to the refer to each method; we just called the NumericOperation() function by passing the required value and typedef variable mp. It performed the given operations and printed the result. Dart Debugging Debugging is the process of identifying and eliminating of existing and possible errors in the Dart program that can cause ambiguity and uncertainty during the program execution. Debugging is essential to detect and fixes the bugs to run the program smoothly or without interruption. Debugging becomes easier if you are using the IDE for the Dart program. Here we are assuming that you have installed the most common and suitable IDE WebStorme in your system. The WebStorm Editor allows us to step by step debugging. What are Breakpoints? Breakpoints are the checkpoint of the program to break the program at a specific point to checks its behavior. We can add the breakpoints in the program to check the bugs within that specific area. How to add Breakpoints in WebStorm? We can add the breakpoints in WebStorm by simply click on a line number in the left bar to add a breakpoint. After adding the breakpoints, run the program in the debug mode, it will give the Debugger window where we can verify that how the breakpoint works. We can also change the values and see the difference in the watches window.
Exceptions
Dart Exceptions are the run-time error. It is raised when the program gets execution. The program doesn’t report the error at compile time when the program runs internally and if Dart compiler found something not appropriate. Then, it reports run-time error and the execution of program is terminated abnormally. This type of error is called Exceptions. For example – A given number is divided by the zero or we try to access the elements from the empty list. Dart supports the following types of built-in exceptions. Sr. Exceptions Description 1. DefferedLoadException It is thrown when a deferred library fails to load. 2. FromatException It is the exception which is thrown 3. IntegerDivisionByZeroException It is thrown when number is divided by zero. 4. IOEException It is the base class of input-output related exception. 5. IsolateSpawnException It is thrown when an isolated cannot be created. 6. Timeout It is thrown when a schedule timeout happens while waiting for an async result. The main objective of the exception is to handle the run-time error and prevent the program from terminating abruptly. Every exception in the Dart is a subtype of the pre-defined class Exception. Dart provides the following techniques to handle the exceptions. The try/on/catch Blocks The try block is used to hold the block of code that might be thrown an exception. The on block is used to when we require specifying the exceptions. The catch block is used to when handler needs the exception object. If the try block finds the error, it throws to the catch block and the catch block has the code to handle the error. The try block must be followed by the exactly one block either on/ catch or one finally block. The syntax of exceptional handling is the given below. Syntax: One should remember the following points. In the following example, the variable x is divided by the y variable respectively. The code is thrown when it tries to divide by the zero. The on block consists of the code to handle the exception. Let’s understand the following code. Example – Using the on block Output Explanation: In the above code, we declared the three variable x, y and res in main () function. We written the suspect code in try block divided the x by the 0 that might be thrown an exception. The try block found the error the control transferred to the on block that has the code to handle the error. By using this, the program did not stop its execution. Let’s understand the following example using the catch block. Example – Using the catch Block Output Now look at the example of on…catch block together Example 3: on…catch block Output The Finally Block The finally block always executes whether there is exception occur or not. It executes unconditionally after the try/on/catch. The syntax of finally block is given below. Syntax – Let’s understand the following example of finally block. Example – Output Throwing an Exception We can raise an exception explicitly or forcefully. The explicitly raised exception should be handled to avoid the program from existing sharply. The syntax is given below. Syntax: Let’s understand the following example. Example – Output Custom Exceptions As we discussed above, each of the exception in dart is the subtype of the built-in class Exception. Dart provide the flexibility to create custom exception by extending the existing exception class. The syntax is given below. Syntax: Defining the Exception Let’s understand the following code. Example – Output Explanation: In the above example, we created a custom exception, AmtException. The code raised the exception if the entered amount is not within the excepted range and we enclosed the function invocation in the try…catch block.
Interfaces
An interface defines the syntax that any entity must adhere to. Dart does not have any separate syntax to define interfaces. An Interface defines the same as the class where any set of methods can be accessed by an object. The Class declaration can interface itself. The keyword implement is needed to be writing, followed by class name to be able to use the interface. Implementing class must provide a complete definition of all the functions of the implemented interface. We can say that a class must define every function with the body in the interface that we want to achieve. Declaring an Interface Dart doesn’t provide syntax for declaring interface directly. Implicitly, a class declaration itself an interface containing the entire instance member of the class and of any interfaces it implements. Implementing an Interface To work with interface methods, the interface must be implemented by another class using the implements keyword. A class which is implemented the interface must provide a full implementation of all the methods that belongs to the interface. Following is the syntax of the implementing interface. Syntax: In the following example, we are declaring a class Employee. Implicit, the Engineer class implements the interface declaration for the Employee class. Let’s understand the above example by the following code snippet. Example – Output: Explanation In the above example, we defined a class Engineer as an interface implementing the Engineer class. Then, we defined the same method display() in both classes. This method override in class Engineer, so we created the object of the Engineer class in a main() function invoked the display() function. It printed the output to the screen. Implementing Multiple Inheritance We have discussed previously that the multiple inheritance is not supported by the Dart, but we can apply the multiple interfaces. We can say that, using multiple interfaces, we can achieve multiple inheritance in Dart. The syntax is given below. Syntax: Let’s understand the following example. Example – Output: Explanation: In the above example, we implemented multiple interfaces in class College. Each data member of Student and Faculty class is overriding in class College. We created the object of College class and invoked the overriding functions. It printed the result. Rules for Implementing Interfaces
Abstract Classes
Abstract classes are the classes in Dart that has one or more abstract method. Abstraction is a part of the data encapsulation where the actual internal working of the function hides from the users. They interact only with external functionality. We can declare the abstract class by using the abstract keyword. There is a possibility that an abstract class may or may not have abstract methods. Abstract methods are those methods, which are declared without implementation. The concrete methods or normal methods are declared with implementation. An abstract class can contain both types of methods, but a normal class is not allowed to have abstract methods. We cannot create the instance of an abstract class that means it can’t be instantiated. It can only be extended by the subclass, and the subclass must be provided the implantation to the abstract methods which are present in the present class. Then it is necessary to declare abstract subclass. Rules for Abstract classes: The rules of the abstract are given below. Declaring Abstract Class An abstract keyword followed by a class name is used to declare the abstract class. An abstract class mostly used to offer a base for the subclass to extends and implement the abstract method. Syntax: Usage of Abstract class Let’s suppose we have a class Person that has method displayInfo(), and we have to sub classes of it Boy and Girl. Each of the person information varies from the other person, so there is no benefit to implementing the displayInfo() in the parent class. Because every subclass must override the parent class method by provides its own implementation. Thus, we can force the subclass to provide implementation to that method, so that is the benefit to make method abstract. We don’t require the give implementation in the parent class. Let’s understand the above scenario through the following code. Example – Output Explanation: As we can see that in the above code, we implemented the abstract method in two subclasses according to its requirement and then we called the displayInfo() method using the object of the both class’s object.
Getters and Setters
Getters and setters are the special class method that is used to read and write access to an object’s properties. The getter method is used to reads the value of the variable or retrieve the value and setter method is used to set or initialize respective class fields. By default, all classes are associated with getter and setter method. However, we can override the default methods by defining getter and setter method explicitly. Defining a getter We can define the getters method by using the get keyword with no parameter a valid return type. Syntax: Defining a setter We can declare the setter method using the set keyword with one parameter and without return type. Syntax: Example: Output We can also place the getter and setter method just after the. Now, let’s understand the following example: Example – 2 Output Explanation: In the above code, we defined the getter and setter methods before the constructor.