Given the 'gold rush' of technological innovations targeting the mobile space, developing mobile apps has never been easier, thanks to cross-platform solutions like Flutter, React Native, NativeScript, PhoneGap, and more.
Flutter, in particular, has successfully captured the attention of the development community by offering an expressive style that makes building UIs for mobile apps enjoyable. It includes concepts familiar to modern development, like reactive programming and widget composition, using the Dart platform as its main base.
Prefer a Video?
So what's Dart?
Dart is an object-oriented programming language by Google, which aims to help the developer build modern web applications. It covers client, server and now mobile with Flutter. It comes with a range of tools including a virtual machine, core libraries and package management repository, lending enough ammunition to get started with on your next project.
Although Flutter is gaining traction, it can easily obscure the beauty of the Dart platform and what it offers, independently of Flutter.
In this article we will look at how we can write a Dart program, exploring some of its language features. This will hopefully gear you up with an overview to help you see Dart shining through as you develop your next app.
First steps
Here's an example of a simple Dart program:
class Order {
var _id;
var _reference;
var _date;
Order(id, reference, date) {
this._id = id;
this._reference = reference;
this._date = date;
}
getInfo() {
return 'Your order information:' +
'\n-------------------------------' +
'\n Id: $_id' +
'\n Reference: $_reference' +
'\n Date: $_date' +
'\n-------------------------------';
}
}
void main() {
var order1 = new Order(1, 'ref1', new DateTime.now());
print(order1.getInfo());
// Expected output
// Your order information:
// -------------------------------
// Id: 1
// Reference: ref1
// Date: 2018-04-21 19:06:20.507
// -------------------------------
}
This demonstrates the blueprint for an Order
with properties and methods. The main()
top-level function is where you would bootstrap your Dart application.
Here, I’m hoping you’ll begin to see how the syntax looks pretty familiar with other OO languages, feeling right at home if you’ve programmed in Java, C# or even JavaScript(ES2015 and above).
That being said, Dart comes with some language features that will surely make you more productive as a developer. See this tweak to our earlier class:
class Order {
var _id;
var _reference;
var _date;
Order(this._id, this._reference, this._date);
getInfo() {
return 'Your order information:'
'\n-------------------------------'
'\n Id: $_id'
'\n Reference: $_reference'
'\n Date: $_date'
'\n-------------------------------';
}
}
void main() {
var order1 = new Order(1, 'ref1', new DateTime.now());
print(order1.getInfo());
}
Not much done here, however we now have a shorthand constructor that saves the repetition of reassigning the parameters passed into the class properties.
We’re also using adjacent strings by removing the plus(+) symbols from our getInfo
method. Oh, and prefixing class properties with underscore (_) makes them private! It’s conventional and saves the need for typing the private keyword.
So let’s see how far we could go with this. Our constructor parameters are defined in a positional manner. That means they are required. Dart allows us to define parameters that are optional, with two flavours: optional positional and optional named. These essentially allow us to have better flexibility in the way we define and use them:
Order(this._id, this._reference, [date]); // optional positional
Order(this._id, this._reference, {date}); // optional named
And their usage:
new Order(1, 'ref1', new DateTime.now()); // optional positional
new Order(2, 'ref2', date: new DateTime.now()); // optional named
And surely we can map this onto our internal property, although for optional named parameters the property needs to be public:
Order(this._id, this._reference, [this.date]); // optional positional
Order(this._id, this._reference, {this.date}); // optional named
I'm hoping this looks predictable to you so far. Let’s now enforce some type information on our properties:
int _id;
String _reference;
DateTime _date;
Another common feature that OO languages have is the ability to declare a constructor multiple times, differentiated by the amount of parameters you pass into it. Dart instead gives you named constructors, which essentially allows you to add a namespace to your constructor, saving you from worrying about the parameter count:
Order(this._id, this._reference, [this.date]); // normal
Order.withDiscount(this._id, this._reference, this.code); // named
And we’ll instantiate that like so: new Order.withDiscount(...)
. Let’s see our refactoring so far:
class Order {
int _id;
String _reference;
DateTime _date;
String code; // public property
Order(this._id, this._reference, this._date);
Order.withDiscount(this._id, this._reference, {this.code}) {
_date = new DateTime.now();
}
// Shorthand methods FTW!!!
String getInfo() => 'Your order information:'
'\n-------------------------------'
'\n Id: $_id'
'\n Reference: $_reference'
'\n Date: $_date'
'\n-------------------------------';
void printInfo() => print(getInfo());
}
void main() {
Order order1 = new Order.withDiscount(1, 'ref1', code: 'LOVETHEWEEKEND');
order1.printInfo();
}
One last feature I would like to cover are method cascades. These allow you to use the chaining pattern for your getters and setters, made popular by JavaScript libraries namely jQuery. To demonstrate this, we’ll another public property named bookings
:
int _id;
String _reference;
DateTime _date;
String code;
List<String> bookings;
and when we instantiate our object we can do:
Order order1 = new Order.withDiscount(1, 'ref1', 'WEEKENDFTW1')
..code = 'WEEKENDFTW1'
..bookings = ['booking1', 'booking2', 'booking3'];
The double period(..) shows cascading in action which always returns the instance each time. The chaining works with setters and also when you invoke methods.
See the complete solution below:
class Order {
// private properties
int _id;
String _reference;
DateTime _date;
// public properties
String code;
String from;
List<String> bookings;
Order(this._id, this._reference, this._date);
Order.withDiscount(this._id, this._reference, {this.code}) {
_date = new DateTime.now();
}
// Using doc strings to save the multiple linebreaks(\n)
String getInfo() => '''
Your order information:
-------------------------------
Id: $_id
Reference: $_reference
Date: $_date
-------------------------------
''';
void printInfo() => print(getInfo());
}
void main() {
Order order1 = new Order.withDiscount(1, 'ref1', code: 'SPECIALDISCOUNT')
..from = 'Jer O'
..bookings = ['booking1', 'booking2', 'booking3']
..printInfo();
}
Conclusion
Learning Dart before you venture into Flutter development will set you on the right course as you would have learnt the foundational pre-requisites for Flutter cross platform development.
I leave you with a task if you're up for it...Modify the getInfo()
method to see if you can include the other order details :) See the code in the online Dart editor.