Search icon CANCEL
Subscription
0
Cart icon
Your Cart (0 item)
Close icon
You have no products in your basket yet
Arrow left icon
Explore Products
Best Sellers
New Releases
Books
Events
Videos
Audiobooks
Packt Hub
Free Learning
Arrow right icon
timer SALE ENDS IN
0 Days
:
00 Hours
:
00 Minutes
:
00 Seconds
Mastering DART
Mastering DART

Mastering DART: Master the art of programming high-performance applications with Dart

Arrow left icon
Profile Icon Sergey Akopkokhyants
Arrow right icon
$57.99
Full star icon Full star icon Full star icon Full star icon Half star icon 4.6 (5 Ratings)
Paperback Nov 2014 346 pages 1st Edition
eBook
$31.49 $34.99
Paperback
$57.99
Arrow left icon
Profile Icon Sergey Akopkokhyants
Arrow right icon
$57.99
Full star icon Full star icon Full star icon Full star icon Half star icon 4.6 (5 Ratings)
Paperback Nov 2014 346 pages 1st Edition
eBook
$31.49 $34.99
Paperback
$57.99
eBook
$31.49 $34.99
Paperback
$57.99

What do you get with Print?

Product feature icon Instant access to your digital copy whilst your Print order is Shipped
Product feature icon Paperback book shipped to your preferred address
Product feature icon Redeem a companion digital copy on all Print orders
Product feature icon Access this title in our online reader with advanced features
Product feature icon DRM FREE - Read whenever, wherever and however you want
Modal Close icon
Payment Processing...
tick Completed

Shipping Address

Billing Address

Shipping Methods
Table of content icon View table of contents Preview book icon Preview Book

Mastering DART

Chapter 1. Beyond Dart's Basics

Dart is a very young computer language with many interesting features. Dart is a class-based, object-oriented language with optional types, and it can help you write very powerful programs. In this chapter, we will cover the following topics:

  • Modularity and a namespace
  • Functions and closures in different scopes
  • Classes and mixins
  • Methods and operators

Modularity and a namespace

Complex things are the foundation of our world. To understand the complexity of the things around us, it is necessary to understand the parts that make them up. The evolution of complex things is due to functional and behavioral modularity. Functional modularity is the composition of smaller independent components with clear boundaries and functions. Behavioral modularity is mainly about traits and attributes that can evolve independently.

Modularity is nothing new. Earlier, product manufacturers figured out ways to increase the output and quality of the product, while still managing to reduce the cost pressures. They accomplished this through modularity. Modular design can be seen in automotive industry, buildings, and many other industries. Henry Ford introduced the notion of modularity in his assembly line with standardized and interchangeable parts. As a result, he reduced the production cycles and costs to achieve the mass production of his automobiles. A lot of these concepts are still used by many companies today.

Modularity in software development

Representation of complex things as a set of parts is called decomposition. By analogy, the real-world complex software may be broken into functional parts called modules. Each module can be created, changed, tested, used, and replaced separately.

Let's take a look at the benefits of modularity. For the sake of simplicity, we divide them into development and postproduction phases. Each of these phases has its own specific tasks to be solved in the scope of that phase.

The development phase has the following benefits:

  • Each module requires less code.
  • New features or changes can be introduced to modules in isolation, separate from the other modules.
  • Errors can be easily identified and fixed in a module.
  • Modules can be built and tested independently.
  • Programmers writing the modules can collaborate on the same application.
  • The same modules can be reused in many applications.
  • Applications have a main module and many auxiliary modules. Each module encapsulates a specific functionality and each one is integrated through loosely coupled communication channels provided by the main module.

The postproduction phase has the following benefits:

  • Modules kept in a versioning system can be easily maintained and tested
  • Fixed and noninfrastructural changes in a module can be done without affecting other modules

One significant disadvantage of modularity is that it increases complexity when managing many modules, especially when each one is individually versioned, updated, and has dependencies on the other modules.

Modularity in Dart

The Dart language was designed by keeping the modules in mind. Modularity in Dart is realized through packages, libraries, and classes.

A library exposes functionality as a set of interfaces and hides the implementation from the rest of the world. As a concept, it's very similar to the separation of concern between objects in object-oriented programming (OOP). Separating an application into libraries helps minimize tight coupling and makes it easier to maintain the code. A library can be implemented as a simple function, a single class, several classes, or a collection of parts representing the entire API of a library. The Dart application is a library as well.

A package is simply a directory that contains a pubspec.yaml file and may include any number of libraries and resources. The pubspec.yaml file contains significant information about the package, its authors, and its dependencies on other packages. Here is a sample pubspec.yaml file:

name: animation_library
version: 0.1.0
author: Sergey Akopkokhyants
description: Animation library for Web application
dependencies:
  browser: any

The real pubspec.yaml file can have more fields as specified at https://www.dartlang.org/tools/pub/pubspec.html.Before a package can be used, it must be published to a package management system, which is available as an online resource called pub at https://pub.dartlang.org/. To publish and retrieve packages from pub, we use a utility application of the same name. The pub utility uses information about dependencies from the pubspec.yaml file to retrieve all the necessary packages from the following locations:

Dart Editor manages dependencies automatically for you. You can publish your packages right in Dart Editor.

Libraries

A namespace is a container for all the members of a library. A namespace is defined by the library name. A library that is implicitly named has an empty namespace. This results in a conflict when trying to import libraries with the same namespaces. Import library namespace conflicts can be easily avoided with a prefix clause (as) and a name prefix.

The following is an implicitly named library in which all the resources from dart:html are made available within the scope of our library with the prefix dom:

/**
 * Implicitly named library.
 * The dart:core library is automatically imported.
 */
import 'dart:html' as dom;

/**
 * Get [Element] by [id].
 */
dom.Element getById(String id) => dom.querySelector('#$id');

The library namespace make sense only in the Dart environment.

Note

The code that is compiled in JavaScript loses all the library information.

Dart implements encapsulation through privacy. Each member or identifier of a library has one of the two levels of access: private or public. Private members are visible only inside the library in which they are declared. Conversely, members with a public access are visible everywhere. The difference between them is the underscore prefix (_), as shown in the following code:

// Animation library.
library animation;

// Class publicly available everywhere.
class Animation {
  // ...
}

// Class visible only inside library.
class _AnimationLibrary {
  // ...
}

// Variable publicly available everywhere.
var animationSpeed;

The preceding code shows an animation library with two classes and one variable. The Animation class and the animationSpeed variable are public, and therefore visible outside the library. The _AnimationLibrary class is private and it can be used only in the library.

Public access can be managed with the show and hide extensions of the import statement. Use the following show extension with a specific class, which will then be available inside the library in which it is imported:

import 'animation.dart' as animation show Animation;

// Main entry into Dart Web application.
main() {
  // Animate
  new animation.Animation();
}

The animation prefix in the import statement defines the namespace to import the animation.dart library. All members of the animation.dart library are available in the global namespace via this prefix. We are referring to an Animation class with the animation prefix, as shown here:

Libraries

Use the hide extension with a specific class, which will then be unavailable inside the library in which it is imported; everything else from the library will be available, as shown in the following code:

import 'animation.dart' as animation hide Animation;

// Main entry into Dart Web application.
main() {
  // Animate
  var speed = animation.animationSpeed;
}

Now we hide the Animation class, but all the other public members in the namespace animation are still available, as seen in the following screenshot:

Libraries

As you can see, the members of the imported library become invisible. This happens because the library exports members from the public namespace. It can be possible to re-export the imported library with the export statement if this necessary export statement can be managed with show and hide as it was for the import statement, as shown in the following code:

library animation.css;

import 'animation.dart' as animation;
export 'animation.dart' show Animation;

class CssAnimation extends animation.Animation {
  // ...
}

The preceding code shows the animation.css library. We export the Animation class as part of the library namespace. Let's take a look at how we can use them:

Libraries

There are the exported Animation and original CssAnimation classes available for use in our main code. Without the export, the Animation class would be inaccessible in the main code.

Functions and closures in different scopes

I like Dart because everything is an object. Functions are first-class citizens because they support all the operations that are generally available to other types. This means each function have the following properties:

  • They can be named by a variable
  • They can be passed as an argument to a function
  • They can be returned as the result of a function
  • They can be stored in data structures
  • They can be created in any scope

Let's see where and how can we use functions as usual or as first-class citizens.

Naming functions with a variable

Naming functions by variable means that we can create a reference to a function and assign it to a variable, as shown in the following code:

library function_var;

// Returns sum of [a] and [b]
add(a, b) {
  return a + b;
}

// Operation 
var operation;

void main() {
  // Assign reference to function [add]
  operation = add;
  // Execute operation
  var result = operation(2, 1);
  print("Result is ${result}");}");
}

Here is the result of the preceding code:

Result is 3

We have the add function and the operation variable. We assign the reference of the add function to a variable and call the variable as a function later.

Passing a function as an argument to another function

Passing functions as arguments to other functions can be very useful in cases when we need to implement the strategy design pattern to enable the program code to be selected and executed at runtime, as shown in the following code:

library function_param;

// Returns sum of [a] and [b]
add(a, b) {
  return a + b;
}

// Operation executor
executor(operation, x, y) {
  return operation(x, y);
}

void main() {
  // Execute operation
  var result = executor(add, 2, 1);
  print("Result is ${result}");
}

Here is the result of the preceding code:

Result is 3

The global executor function from the preceding example can call any function that accepts two arguments. You can see the implementation of the strategy design pattern in the form of anonymous functions passed as parameters of methods in collections.

Returning a function as a result of another function

Sometimes, a function can be returned as a result of another function, as shown in the following code:

library function_return;

// Returns sum of [a] and [b]
add(a, b) => a + b;

// Returns difference between [a] and [b]
sub(a, b) => a - b;

// Choose the function depends on [type]
chooser(bool operation) =>operation ? add : sub;

void main() {
  // Choose function depends on operation type
  var operation = chooser(true);
  // Execute it
  var result = operation(2, 1);
  // Result
  print("Result is ${result}");
}

Here is the result of the preceding code:

Result is 3

This option can be very useful in implementing closures.

Storing a function in data structures

We can store a function in data structures in any collection, as shown in the following code:

library function_store;

// Returns sum of [a] and [b]
add(a, b) => a + b;

// Returns difference between [a] and [b]
sub(a, b) => a - b;

// Choose the function depends on [type]
var operations = [add, sub];

void main() {
  // Choose function from list
  var operation = operations[0];
  // Execute it
  var result = operation(2, 1);
  // Result
  print("Result is ${result}");
}

Here is the result of the preceding code:

Result is 3

We have two functions and the array operations in our example that stores references to them.

Closures

A function can be created in the global scope or within the scope of another function. A function that can be referenced with an access to the variables in its lexical scope is called a closure, as shown in the following code:

library function_closure;

// Function returns closure function. 
calculate(base) {
  // Counter store
  var count = 1;
  // Inner function - closure
  return () => print("Value is ${base + count++}");
}

void main() {
  // The outer function returns inner
  var f = calculate(2);
  // Now we call closure
  f();
  f();
}

Here is the result of the preceding code:

Value is 3
Value is 4

We have the calculate function, which contains the count variable and returns a an inner function. The inner function has an access to the count variable because both are defined in the same scope. The count variable exists only within the scope of calculate and would normally disappear when the function exits. This does not happen in this case because the inner function returned by calculate holds a reference to count. The variable has been closed covered, meaning it's within a closure.

Finally, we know what a first-class function is, where we can use them, and how important it is to use closures. Let's move ahead to classes and mixins.

Classes and mixins

We all know its wasteful trying to reinvent the wheel. It's even more wasteful trying to do it each time we want to build a car. So how can a program code be written more efficiently and made reusable to help us develop more powerful applications? In most cases, we turn to the OOP paradigm when trying to answer this question. OOP represents the concept of objects with data fields and methods that act on that data. Programs are designed to use objects as instances of classes that interact with each other to organize functionality.

Types

The Dart language is dynamically typed, so we can write programs with or without the type annotations in our code. It's better to use the type annotations for the following reasons:

  • The type annotations enable early error detection. The static analyzer can warn us about the potential problems at the points where you've made the mistakes.
  • Dart automatically converts the type annotations into runtime assertion checks. In the checked mode, the dynamic type assertions are enabled and it can catch some errors when types do not match.
  • The type annotations can improve the performance of the code compiled in JavaScript.
  • They can improve the documentation making it much easier to read the code.
  • They can be useful in special tools and IDE such as the name completion.

The fact that the type annotations were not included in our code does not prevent our program from running. The variables without the type annotations have a dynamic type and are marked with var or dynamic. Here are several recommendations where the type annotations are appropriate:

  • You should add types to public and private variables
  • You can add types to parameters of methods and functions
  • You should avoid adding types to the bodies of methods or functions

Classes

In the real world, we find many individual objects, all of the same kind. There are many cars with the same make and model. Each car was built from the same set of blueprints. All of them contain the same components and each one is an instance of the class of objects known as Car, as shown in the following code:

library car;

// Abstract class [Car] can't be instantiated.
abstract class Car {
  // Color of the car.
String color;
  // Speed of the car.
  double speed;
  // Carrying capacity
  double carrying;

  // Create new [Car] with [color] and [carrying] info.
  Car(this.color, this.carrying);

  // Move car with [speed]
  void move(double speed) {
    this.speed = speed;
  }

  // Stop car.
  void stop() {
    speed = 0.0;
  }
}

Objects have methods and instance variables. The color, speed, and carrying are instance variables. All of them have the value null as they were not initialized. The instance methods move and stop provide the behavior for an object and have access to instance variables and the this keyword. An object may have getters and setters—special methods with the get and set keywords that provide read and write access to the instance variables. The Car class is marked with the abstract modifier, so we can't create an instance of this class, but we can use it to define common characteristics and behaviors for all the subclasses.

Inheritance

Different kinds of objects can have different characteristics that are common with others. Passenger cars, trucks, and buses share the characteristics and behaviors of a car. This means that different kinds of cars inherit the commonly used characteristics and behaviors from the Car class. So, the Car class becomes the superclass for all the different kinds of cars. We allow passenger cars, trucks, and buses to have only one direct superclass. A Car class can have unlimited number of subclasses. In Dart, it is possible to extend from only one class. Every object extends by default from an Object class:

library passenger_car;

import 'car.dart';

// Passenger car with trailer.
class PassengerCar extends Car {
  // Max number of passengers.
  int maxPassengers;

  // Create [PassengerCar] with [color], [carrying] and [maxPassengers].
  PassengerCar(String color, double carrying, this.maxPassengers) : 
    super(color, carrying);
}

The PassengerCar class is not an abstract and can be instantiated. It extends the characteristics of the abstract Car class and adds the maxPassengers variable.

Interface

Each Car class defines a set of characteristics and behaviors. All the characteristics and behaviors of a car define its interface—the way it interacts with the outside world. Acceleration pedal, steering wheel, and other things help us interact with the car through its interface. From our perspective, we don't know what really happens when we push the accelerator pedal, we only see the results of our interaction. Classes in Dart implicitly define an interface with the same name as the class. Therefore, you don't need interfaces in Dart as the abstract class serves the same purpose. The Car class implicitly defines an interface as a set of characteristics and behaviors.

If we define a racing car, then we must implement all the characteristics and behaviors of the Car class, but with substantial changes to the engine, suspension, breaks, and so on:

import 'car.dart';
import 'passenger_car.dart';

void main() {
  // Create an instance of passenger car of white color, 
  // carrying 750 kg and max passengers 5.
  Car car = new PassengerCar('white', 750.0, 5);
  // Move it
  car.move(100.0);
}

Here, we just created an instance of PassengerCar and assigned it to the car variable without defining any special interfaces.

Mixins

Dart has a mixin-based inheritance, so the class body can be reused in multiple class hierarchies, as shown in the following code:

library trailer;

// The trailer
class Trailer {
  // Access to car's [carrying] info
  double carrying = 0.0; 

  // Trailer can carry [weight]
  void carry(double weight) {
    // Car's carrying increases on extra weight.
    carrying += weight;
  }
}

The Trailer class is independent of the Car class, but can increase the carrying weight capacity of the car. We use the with keyword followed by the Trailer class to add mixin to the PassengerCar class in the following code:

library passenger_car;

import 'car.dart';
import 'trailer.dart';

// Passenger car with trailer.
class PassengerCar extends Car with Trailer {
  // Max number of passengers.
  int maxPassengers = 4;

  /**
   * Create [PassengerCar] with [color], [carrying] and [maxPassengers].
   * We can use [Trailer] to carry [extraWeight].
   */
  PassengerCar(String color, double carrying, this.maxPassengers, 
      {double extraWeight:0.0}) : super(color, carrying) {
    // We can carry extra weight with [Trailer]
    carry(extraWeight);
  }
}

We added Trailer as a mixin to PassengerCar and, as a result, PassengerCar can now carry more weight. Note that we haven't changed PassengerCar itself, we've only extended its functionality. At the same time, Trailer can be used in conjunction with the Truck or Bus classes. A mixin looks like an interface and is implicitly defined via a class declaration, but has the following restrictions:

  • It has no declared constructor
  • The superclass of a mixin can only be an Object
  • They do not contain calls to super

Well-designed classes

What is the difference between well-designed and poorly-designed classes? Here are the features of a well-designed class:

  • It hides all its implementation details
  • It separates its interface from its implementation through the use of abstract classes
  • It communicates with other classes only through their interfaces

All the preceding properties lead to encapsulation. It plays a significant role in OOP. Encapsulation has the following benefits:

  • Classes can be developed, tested, modified, and used independently
  • Programs can be quickly developed because classes can be developed in parallel
  • Class optimization can be done without affecting other classes
  • Classes can be reused more often because they aren't tightly coupled
  • Success in the development of each class leads to the success of the application

All our preceding examples include public members. Is that right? So what is the rule that we must follow to create well-designed classes?

To be private or not

Let's follow the simple principles to create a well-designed class:

  • Define a minimal public API for the class. Private members of a class are always accessible inside the library scope so don't hesitate to use them.
  • It is not acceptable to change the level of privacy of the member variables from private to public to facilitate testing.
  • Nonfinal instance variables should never be public; otherwise, we give up the ability to limit the values that can be stored in the variable and enforce invariants involving the variable.
  • The final instance variable or static constant should never be public when referring to a mutable object; otherwise, we restrict the ability to take any action when the final variable is modified.
  • It is not acceptable to have the public, static final instance of a collection or else, the getter method returns it; otherwise, we restrict the ability to modify the content of the collection.

The last two principles can be seen in the following example. Let's assume we have a Car class with defined final static list of parts. We can initialize them with Pedal and Wheel, as shown in the following code:

class Car {
  // Be careful with that code !!!
static final List PARTS = ['Pedal', 'Wheel'];
}
void main() {
  print('${Car.PARTS}'); // Print: [Pedal, Wheel]

  // Change part
  Car.PARTS.remove('Wheel');
  print('${Car.PARTS}'); // Print: [Pedal]
}

However, there's a problem here. While we can't change the actual collection variable because it's marked as final, we can still change its contents. To prevent anyone from changing the contents of the collection, we change it from final to constant, as shown in the following code:

class Car {
  // This code is safe
  static const List PARTS = const ['Pedal', 'Wheel'];
}

void main() {
  print('${Car.PARTS}'); // Print: [Pedal, Wheel]

  // Change part
  Car.PARTS.remove('Wheel');
  print('${Car.PARTS}');
}

This code will generate the following exception if we try to change the contents of PARTS:

Unhandled exception:
Unsupported operation: Cannot modify an immutable array
#0 List.remove (dart:core-patch/array.dart:327)
…

Variables versus the accessor methods

In the previous section, we mentioned that nonfinal instance variables should never be public, but is this always right? Here's a situation where a class in our package has a public variable. In our Car class, we have a color field and it is deliberately kept as public, as shown in the following code:

// Is that class correct?
class Car {
  // Color of the car.
  String color;
}

If the Car class is accessible only inside the library, then there is nothing wrong with it having public fields, because they don't break the encapsulation concept of the library.

Inheritance versus composition

We defined the main rules to follow and create a well-designed class. Everything is perfect and we didn't break any rules. Now, it's time to use a well-designed class in our project. First, we will create a new class that extends the current one. However, that could be a problem as inheritance can break encapsulation.

It is always best to use inheritance in the following cases:

  • Inside the library, because we control the implementation and relationship between classes
  • If the class was specifically designed and documented to be extended

It's better not to use inheritance from ordinary classes because it's dangerous. Let's discuss why. For instance, someone developed the following Engine class to start and stop the general purpose engine:

// General purpose Engine
class Engine {
  // Start engine
  void start() {
     // ...
  }

  // Stop engine
  void stop() {
    // ...
  }
}

We inherited the DieselEngine class from the Engine class and defined when to start the engine that we need to initialize inside the init method, as shown in the following code:

import 'engine.dart';

// Diesel Engine
class DieselEngine extends Engine {
  DieselEngine();

  // Initialize engine before start
  void init() {
    // ...
  }
  void start() {
   // Engine must be initialized before use
   init();
   // Start engine
   super.start();
  }
}

Then, suppose someone changed their mind and decided that the implementation Engine must be initialized and added the init method to the Engine class, as follows:

// General purpose Engine
class Engine {
  // Initialize engine before start
  void init() {
    // ...
  }

  // Start engine
  void start() {
    init();
  }

  // Stop engine
  void stop() {
    // ...
  }
}

As a result, the init method in DieselEngine overrides the same method from the Engine superclass. The init method in the superclass is an implementation detail. The implementation details can be changed many times in future from release to release. The DieselEngine class is tightly-coupled with and depends on the implementation details of the Engine superclass. To fix this problem, we can use a different approach, as follows:

import 'engine.dart';

// Diesel Engine
class DieselEngine implements Engine {
  Engine _engine;

  DieselEngine() {
    _engine = new Engine();
  }

  // Initialize engine before start
  void init() {
    // ...
  }

  void start() {
    // Engine must be initialized before use
    init();
    // Start engine
    _engine.start();
  }

  void stop() {
    _engine.stop();
  }
}

We created the private engine variable in our DieselEngine class that references an instance of the Engine class. Engine now becomes a component of DieselEngine. This is called a composition. Each method in DieselEngine calls the corresponding method in the Engine instance. This technique is called forwarding, because we forward the method's call to the instance of the Engine class. As a result, our solution is safe and solid. If a new method is added to Engine, it doesn't break our implementation.

The disadvantages of this approach are associated performance issues and increased memory usage.

Methods and operators

Now that we've introduced well-designed classes, we need to discuss methods.

Checking the values of the parameters before using them

The class constructors, methods, mutators (setters), and operators remove some restrictions on the values that must be passed into their parameters .What will happen if an invalid parameter value is passed to a method? One possibility is that the method will fail with a confusing exception or worse it will succeed but with a wrong result. In any case, it's dangerous not check the parameters of a method before using them. The rule here is to check whether the parameter value is valid as soon as possible. The best place to do that is at the beginning of the method.

The Dart VM can work in a developer-friendly checked mode and a speed-obsessed production mode. We usually use the checked mode when developing our applications. One of the benefits of this mode is the dynamic assertion. We should use the assert statement to check whether the parameters of the method are valid before using it. The Dart VM continues the program execution if the Boolean result of the dynamic assertion is true, otherwise stops it. This is shown in the following code:

/**
 * Return sum of [a] and [b].
 * It throws [AssertionError] if any of [a] or [b] equals null  
 */
sum(int a, int b) {
  assert(a != null);
  assert(b != null);
  return a + b;
}

Note

The assert statement has no effect when the program executes in the production mode or is compiled with the JavaScript code.

We must check the validity of the parameters stored in the method for later use. Ignoring this can lead to problems later because an error associated with the parameter can be thrown in a completely different place, making it harder to trace its source. This has serious implications, especially in constructors.

Sometimes, it is important to validate the internal state of a class in the method and generate a special error, as shown in the following code. The typical errors are StateError, RangeError, and ArgumentError.

class Car {
  double petrol;

  /**
   * Start engine.
   * That method throws [StateError] if petrol is null 
   * or less than 5 liters.
   */
  void startEngine() {
    if (petrol == null || petrol <= 5.0) {
      throw new StateError('Not enough petrol');
    }
  }
}

Here, we have a Car class with the petrol variable and the startEngine method. The startEngine method checks whether there is enough petrol to start the engine; otherwise, it throws an error.

Note

Each time you create a method, think about the restrictions that apply to its parameters.

Well-designed methods

So, now that we've defined well-designed classes, it's time to define well-designed methods. We must remember that methods are part of a class' interface and the following simple rules can make them easier to use and also less error-prone:

  • Choose the right method name. Remember, Dart doesn't support method overloading. Instead, we can have different method names or optional parameters.
  • Use optional named parameters. This helps programmers to use your methods without the need to remember the position of each parameter.
  • Refer to objects in terms of their interfaces over classes as the type of parameters. For example, we have an interface and the class implements that interface. Use the interface as the parameter type of the method instead of a solid one. Don't restrict the solution to a particular implementation.

A car may have the following different types of engines:

// Engine interface
abstract class Engine {
  void start();
}

// Diesel engine
class DieselEngine implements Engine {
  void start() {
    // ...
  }
}

// Carburetor engine
class CarburetorEngine implements Engine {
  void start() {
    // ...
  }
}

// Car
class Car {
  var engine;

  // Car may have any engine
  Car(Engine this.engine);
}

It's better to pass the abstract Engine class as a parameter of the constructor for the car to prevent any problems in future.

Tip

Downloading the example code

You can download the example code files for all Packt books you have purchased from your account at http://www.packtpub.com. If you purchased this book elsewhere, you can visit http://www.packtpub.com/support and register to have the files e-mailed directly to you.

Summary

This chapter covered some of the most useful advanced features of the Dart language. The Dart language was designed with the modules in mind. Modularity in Dart is realized through packages, libraries, and classes. The code compiled in JavaScript loses all the library information.

Functions are first-class citizens because they support all the operations generally available to other types. A function that can be referenced with an access to the variables in its lexical scope is called a closure.

Programs are designed to use objects as instances of classes that interact with each other to organize functionality. The Dart language is dynamically typed, so we can write programs with or without the type annotations in our code.

In the next chapter, we will talk about generics, errors and exceptions, and annotations and reflection.

Left arrow icon Right arrow icon

Description

If you are an application developer who has experience with Dart and want to develop reusable and robust code in Dart, then this book is for you. You are expected to have a basic knowledge of core elements and applications.

What you will learn

  • Build applications easily using the eventdriven paradigm
  • Familiarize yourself with asynchronous programming
  • Understand when and how to use collections to store and manipulate groups of objects
  • Use Dart and JavaScript together to build web applications
  • Add internalization and localization support to your application to improve its performance
  • Organize clienttoserver communication and discover the protocols for specific scenarios
  • Detect and use HTML5 features that will help you deliver rich, crossplatform content
  • Discover different techniques to secure your web application from unauthorized users
Estimated delivery fee Deliver to United States

Economy delivery 10 - 13 business days

Free $6.95

Premium delivery 6 - 9 business days

$21.95
(Includes tracking information)

Product Details

Country selected
Publication date, Length, Edition, Language, ISBN-13
Publication date : Nov 20, 2014
Length: 346 pages
Edition : 1st
Language : English
ISBN-13 : 9781783989560
Category :
Languages :

What do you get with Print?

Product feature icon Instant access to your digital copy whilst your Print order is Shipped
Product feature icon Paperback book shipped to your preferred address
Product feature icon Redeem a companion digital copy on all Print orders
Product feature icon Access this title in our online reader with advanced features
Product feature icon DRM FREE - Read whenever, wherever and however you want
Modal Close icon
Payment Processing...
tick Completed

Shipping Address

Billing Address

Shipping Methods
Estimated delivery fee Deliver to United States

Economy delivery 10 - 13 business days

Free $6.95

Premium delivery 6 - 9 business days

$21.95
(Includes tracking information)

Product Details

Publication date : Nov 20, 2014
Length: 346 pages
Edition : 1st
Language : English
ISBN-13 : 9781783989560
Category :
Languages :

Packt Subscriptions

See our plans and pricing
Modal Close icon
$19.99 billed monthly
Feature tick icon Unlimited access to Packt's library of 7,000+ practical books and videos
Feature tick icon Constantly refreshed with 50+ new titles a month
Feature tick icon Exclusive Early access to books as they're written
Feature tick icon Solve problems while you work with advanced search and reference features
Feature tick icon Offline reading on the mobile app
Feature tick icon Simple pricing, no contract
$199.99 billed annually
Feature tick icon Unlimited access to Packt's library of 7,000+ practical books and videos
Feature tick icon Constantly refreshed with 50+ new titles a month
Feature tick icon Exclusive Early access to books as they're written
Feature tick icon Solve problems while you work with advanced search and reference features
Feature tick icon Offline reading on the mobile app
Feature tick icon Choose a DRM-free eBook or Video every month to keep
Feature tick icon PLUS own as many other DRM-free eBooks or Videos as you like for just $5 each
Feature tick icon Exclusive print discounts
$279.99 billed in 18 months
Feature tick icon Unlimited access to Packt's library of 7,000+ practical books and videos
Feature tick icon Constantly refreshed with 50+ new titles a month
Feature tick icon Exclusive Early access to books as they're written
Feature tick icon Solve problems while you work with advanced search and reference features
Feature tick icon Offline reading on the mobile app
Feature tick icon Choose a DRM-free eBook or Video every month to keep
Feature tick icon PLUS own as many other DRM-free eBooks or Videos as you like for just $5 each
Feature tick icon Exclusive print discounts

Frequently bought together


Stars icon
Total $ 177.97
Learning Dart
$68.99
Mastering DART
$57.99
DART Cookbook
$50.99
Total $ 177.97 Stars icon

Table of Contents

13 Chapters
1. Beyond Dart's Basics Chevron down icon Chevron up icon
2. Advanced Techniques and Reflection Chevron down icon Chevron up icon
3. Object Creation Chevron down icon Chevron up icon
4. Asynchronous Programming Chevron down icon Chevron up icon
5. The Stream Framework Chevron down icon Chevron up icon
6. The Collection Framework Chevron down icon Chevron up icon
7. Dart and JavaScript Interoperation Chevron down icon Chevron up icon
8. Internalization and Localization Chevron down icon Chevron up icon
9. Client-to-server Communication Chevron down icon Chevron up icon
10. Advanced Storage Chevron down icon Chevron up icon
11. Supporting Other HTML5 Features Chevron down icon Chevron up icon
12. Security Aspects Chevron down icon Chevron up icon
Index Chevron down icon Chevron up icon

Customer reviews

Rating distribution
Full star icon Full star icon Full star icon Full star icon Half star icon 4.6
(5 Ratings)
5 star 80%
4 star 0%
3 star 20%
2 star 0%
1 star 0%
Honest Dime Apr 08, 2015
Full star icon Full star icon Full star icon Full star icon Full star icon 5
Mastering Dart by Sergey Akopkokhyants takes Dart to a new level. This book assumes you have application programming background like Dart, Java or C#.Highlights of the book.- talks about best practices. So gives rule of thumb approach.- explains design patterns like factory pattern, singleton pattern.- has conversational style of explanation that makes me feel the author takes us along.- focus on concurrency - which is a good thing. EDA, isolates, etc. This is an enterprise grade rich language.- concept of streams for pipelining tasks.- author shares some opinions like variables-or-accessor methods, inheritance-vs-composition.- Provides some useful references to profiling tools like wrk.Chapter wise core topicsChapter 1: Beyond Dart's Basics: Core topics: passing functions around, closures and mixins.Chapter 2: Advanced Techniques and Reflection Core topics: annotations, proxies and reflectionChapter 3: Object Creation Core topics: types of constructors- named constructor, redirecting constructor, private, factory constructors and initializing variables.Chapter 4: Asynchronous Programming Core topics: Dart VM execution model, call-vs-event stack architecture and differences between them, futures, zones(configurable execution context) and isolates.Chapter 5: The Stream Framework Core topics: streams - types and management, event sinks.Chapter 6: The Collection Framework Core topics: "usual" collection and more.Chapter 7: Dart and JavaScript Interoperation Core topics: Interaction with jQuery.Chapter 8: Internalization and Localization Core topics: "usual" stuff.Chapter 9: Client-to-server Communication Core topics: Handling HTTP request and response streams, AJAX (long)polling, server-sent events.Chapter 10: Advanced Storage Core topics: Cookies, Web Storage, Web SQL and IndexedDBChapter 11: Supporting Other HTML5 Features Core topics: Web Notification, drag-and-drop, geolocation APIs and CanvasChapter 12: Security Aspects Core topics: Web security, Securing a server, Securing a client and best practices.There is this sentence, "The website must have permission before use your location information." The author could have had the book proof read well. But as long as such sentence constructs do not have material ambiguity, I am willing to give the benefit of doubt.What I like most is the methodical flow of topics that builds on foundation and leaves us at the optimal level to explore things for ourselves based on the needs of the project.Disclosure: I got a copy to review and am not compensated for this review. My background is J2EE/backend stuff. For a person with purely UI background (HTML/CSS/Javascript), this may not be the best book to start with, IMHO.
Amazon Verified review Amazon
Jeffrey Johnson Jan 21, 2015
Full star icon Full star icon Full star icon Full star icon Full star icon 5
Even though this book covers advanced topics, it doesn't storm ahead, leaving the reader trying to play catch-up. Examples and chapters build, in comfortable increments, on previous ones and there's hardly any "but more on that later" as I've seen in many other books.Sergey manages to stay focused on the advanced topics without falling into the trap of rehashing the basics of Dart. His writing is simple and to the point and I appreciate that.Topics are discussed in detail and I didn't feel that he'd glossed over any of them. I'm not a Dart developer myself, yet I was able to grasp the concepts fairly easily. There was hardly any of that "what did I just read" feeling I get with some books.(Disclosure: I know and work with the author)
Amazon Verified review Amazon
Dima Jan 21, 2015
Full star icon Full star icon Full star icon Full star icon Full star icon 5
Great book that delving deep into Dart. Must have for learning Dart, absolutely.
Amazon Verified review Amazon
Corneliu Dascalu Dec 27, 2014
Full star icon Full star icon Full star icon Full star icon Full star icon 5
I really enjoyed it. I found it suitable for my level of experience with Dart (beginner). The author doesn't insist on basic stuff that can be easily found in the official docs, but explains in-depth the more advanced features of Dart.I feel that I have learned a lot, and that I can use the book as a resource for future projects.
Amazon Verified review Amazon
Paul Jan 19, 2015
Full star icon Full star icon Full star icon Empty star icon Empty star icon 3
There are not many Dart books published yet but there is some good information collected in this book. I disagree with some of the content, but chapters are a good length and have decent summaries.I would recommend it only for experienced developers that are healthily skeptical about things claimed to be “good practice” and “high performance” throughout the book.To be fair the blurb on the site also warns it requires some experience, but I surmise for different reasons. The book feels like it is imposing Java and enterprise ideals on Dart. Dart does not need all that baggage – even if the language itself enables it. To an impressionable mind this book could encourage some poor engineering choices.For example it uses object composition examples based on real life concepts – an inexperienced programmer might take that literally… modeling for real life rather than for how data is best represented and manipulated. There are no warnings about the cost of using reflection, how either type of optional parameter makes life harder for Dart and Javascript VMs, costs of object instantiation or the different types of function calls presented. There are many places throughout the book a novice could be mislead down a very poorly performing path.There are English language errors throughout. Catched rather than caught, angel rather than angle. There are a few phrases that sound conversational and a little out of place. It sometimes made reading a little jarring. I believe these issues could be solved with another editorial pass, but this version lacks polish.The book redeems itself back to three out of five when the reader has confidence to ignore the overtly enterprise style code. The language features and packages presented in later chapters were more useful.I have an e-copy of the book from Packt and read it entirely on a Kindle Paperwhite. The main text was typeset quite nicely and with the smallest font on my Kindle Paperwhite the code samples mostly fit on single lines.Disclosure: I was given a review copy and no compensation.
Amazon Verified review Amazon
Get free access to Packt library with over 7500+ books and video courses for 7 days!
Start Free Trial

FAQs

What is the digital copy I get with my Print order? Chevron down icon Chevron up icon

When you buy any Print edition of our Books, you can redeem (for free) the eBook edition of the Print Book you’ve purchased. This gives you instant access to your book when you make an order via PDF, EPUB or our online Reader experience.

What is the delivery time and cost of print book? Chevron down icon Chevron up icon

Shipping Details

USA:

'

Economy: Delivery to most addresses in the US within 10-15 business days

Premium: Trackable Delivery to most addresses in the US within 3-8 business days

UK:

Economy: Delivery to most addresses in the U.K. within 7-9 business days.
Shipments are not trackable

Premium: Trackable delivery to most addresses in the U.K. within 3-4 business days!
Add one extra business day for deliveries to Northern Ireland and Scottish Highlands and islands

EU:

Premium: Trackable delivery to most EU destinations within 4-9 business days.

Australia:

Economy: Can deliver to P. O. Boxes and private residences.
Trackable service with delivery to addresses in Australia only.
Delivery time ranges from 7-9 business days for VIC and 8-10 business days for Interstate metro
Delivery time is up to 15 business days for remote areas of WA, NT & QLD.

Premium: Delivery to addresses in Australia only
Trackable delivery to most P. O. Boxes and private residences in Australia within 4-5 days based on the distance to a destination following dispatch.

India:

Premium: Delivery to most Indian addresses within 5-6 business days

Rest of the World:

Premium: Countries in the American continent: Trackable delivery to most countries within 4-7 business days

Asia:

Premium: Delivery to most Asian addresses within 5-9 business days

Disclaimer:
All orders received before 5 PM U.K time would start printing from the next business day. So the estimated delivery times start from the next day as well. Orders received after 5 PM U.K time (in our internal systems) on a business day or anytime on the weekend will begin printing the second to next business day. For example, an order placed at 11 AM today will begin printing tomorrow, whereas an order placed at 9 PM tonight will begin printing the day after tomorrow.


Unfortunately, due to several restrictions, we are unable to ship to the following countries:

  1. Afghanistan
  2. American Samoa
  3. Belarus
  4. Brunei Darussalam
  5. Central African Republic
  6. The Democratic Republic of Congo
  7. Eritrea
  8. Guinea-bissau
  9. Iran
  10. Lebanon
  11. Libiya Arab Jamahriya
  12. Somalia
  13. Sudan
  14. Russian Federation
  15. Syrian Arab Republic
  16. Ukraine
  17. Venezuela
What is custom duty/charge? Chevron down icon Chevron up icon

Customs duty are charges levied on goods when they cross international borders. It is a tax that is imposed on imported goods. These duties are charged by special authorities and bodies created by local governments and are meant to protect local industries, economies, and businesses.

Do I have to pay customs charges for the print book order? Chevron down icon Chevron up icon

The orders shipped to the countries that are listed under EU27 will not bear custom charges. They are paid by Packt as part of the order.

List of EU27 countries: www.gov.uk/eu-eea:

A custom duty or localized taxes may be applicable on the shipment and would be charged by the recipient country outside of the EU27 which should be paid by the customer and these duties are not included in the shipping charges been charged on the order.

How do I know my custom duty charges? Chevron down icon Chevron up icon

The amount of duty payable varies greatly depending on the imported goods, the country of origin and several other factors like the total invoice amount or dimensions like weight, and other such criteria applicable in your country.

For example:

  • If you live in Mexico, and the declared value of your ordered items is over $ 50, for you to receive a package, you will have to pay additional import tax of 19% which will be $ 9.50 to the courier service.
  • Whereas if you live in Turkey, and the declared value of your ordered items is over € 22, for you to receive a package, you will have to pay additional import tax of 18% which will be € 3.96 to the courier service.
How can I cancel my order? Chevron down icon Chevron up icon

Cancellation Policy for Published Printed Books:

You can cancel any order within 1 hour of placing the order. Simply contact customercare@packt.com with your order details or payment transaction id. If your order has already started the shipment process, we will do our best to stop it. However, if it is already on the way to you then when you receive it, you can contact us at customercare@packt.com using the returns and refund process.

Please understand that Packt Publishing cannot provide refunds or cancel any order except for the cases described in our Return Policy (i.e. Packt Publishing agrees to replace your printed book because it arrives damaged or material defect in book), Packt Publishing will not accept returns.

What is your returns and refunds policy? Chevron down icon Chevron up icon

Return Policy:

We want you to be happy with your purchase from Packtpub.com. We will not hassle you with returning print books to us. If the print book you receive from us is incorrect, damaged, doesn't work or is unacceptably late, please contact Customer Relations Team on customercare@packt.com with the order number and issue details as explained below:

  1. If you ordered (eBook, Video or Print Book) incorrectly or accidentally, please contact Customer Relations Team on customercare@packt.com within one hour of placing the order and we will replace/refund you the item cost.
  2. Sadly, if your eBook or Video file is faulty or a fault occurs during the eBook or Video being made available to you, i.e. during download then you should contact Customer Relations Team within 14 days of purchase on customercare@packt.com who will be able to resolve this issue for you.
  3. You will have a choice of replacement or refund of the problem items.(damaged, defective or incorrect)
  4. Once Customer Care Team confirms that you will be refunded, you should receive the refund within 10 to 12 working days.
  5. If you are only requesting a refund of one book from a multiple order, then we will refund you the appropriate single item.
  6. Where the items were shipped under a free shipping offer, there will be no shipping costs to refund.

On the off chance your printed book arrives damaged, with book material defect, contact our Customer Relation Team on customercare@packt.com within 14 days of receipt of the book with appropriate evidence of damage and we will work with you to secure a replacement copy, if necessary. Please note that each printed book you order from us is individually made by Packt's professional book-printing partner which is on a print-on-demand basis.

What tax is charged? Chevron down icon Chevron up icon

Currently, no tax is charged on the purchase of any print book (subject to change based on the laws and regulations). A localized VAT fee is charged only to our European and UK customers on eBooks, Video and subscriptions that they buy. GST is charged to Indian customers for eBooks and video purchases.

What payment methods can I use? Chevron down icon Chevron up icon

You can pay with the following card types:

  1. Visa Debit
  2. Visa Credit
  3. MasterCard
  4. PayPal
What is the delivery time and cost of print books? Chevron down icon Chevron up icon

Shipping Details

USA:

'

Economy: Delivery to most addresses in the US within 10-15 business days

Premium: Trackable Delivery to most addresses in the US within 3-8 business days

UK:

Economy: Delivery to most addresses in the U.K. within 7-9 business days.
Shipments are not trackable

Premium: Trackable delivery to most addresses in the U.K. within 3-4 business days!
Add one extra business day for deliveries to Northern Ireland and Scottish Highlands and islands

EU:

Premium: Trackable delivery to most EU destinations within 4-9 business days.

Australia:

Economy: Can deliver to P. O. Boxes and private residences.
Trackable service with delivery to addresses in Australia only.
Delivery time ranges from 7-9 business days for VIC and 8-10 business days for Interstate metro
Delivery time is up to 15 business days for remote areas of WA, NT & QLD.

Premium: Delivery to addresses in Australia only
Trackable delivery to most P. O. Boxes and private residences in Australia within 4-5 days based on the distance to a destination following dispatch.

India:

Premium: Delivery to most Indian addresses within 5-6 business days

Rest of the World:

Premium: Countries in the American continent: Trackable delivery to most countries within 4-7 business days

Asia:

Premium: Delivery to most Asian addresses within 5-9 business days

Disclaimer:
All orders received before 5 PM U.K time would start printing from the next business day. So the estimated delivery times start from the next day as well. Orders received after 5 PM U.K time (in our internal systems) on a business day or anytime on the weekend will begin printing the second to next business day. For example, an order placed at 11 AM today will begin printing tomorrow, whereas an order placed at 9 PM tonight will begin printing the day after tomorrow.


Unfortunately, due to several restrictions, we are unable to ship to the following countries:

  1. Afghanistan
  2. American Samoa
  3. Belarus
  4. Brunei Darussalam
  5. Central African Republic
  6. The Democratic Republic of Congo
  7. Eritrea
  8. Guinea-bissau
  9. Iran
  10. Lebanon
  11. Libiya Arab Jamahriya
  12. Somalia
  13. Sudan
  14. Russian Federation
  15. Syrian Arab Republic
  16. Ukraine
  17. Venezuela
Modal Close icon
Modal Close icon