Slide 1

Slide 1 text

Flutter & Dart Records & Patterns: A productivity hack in Dart 3

Slide 2

Slide 2 text

Mobile Engineer Google Developer Expert Flutter & Dart @_iamEtornam Etornam Sunu Bright About me

Slide 3

Slide 3 text

Dart 3 is the latest version of the Dart programming language. It introduces a number of new features that make it more reliable and productive. ● Records ● Patterns Features

Slide 4

Slide 4 text

Feature #2 Records

Slide 5

Slide 5 text

Records are a new type in Dart that lets you aggregate multiple values of different types in a single function return. This makes it easier to work with structured data. Records are similar to classes in that they can contain fields, but they are different in several ways. Records are anonymous, meaning that they do not have a name. They are also immutable, meaning that their fields cannot be changed after they are created. Finally, records are structurally typed, meaning that their type is determined by the types of their fields. What are Records? Records

Slide 6

Slide 6 text

final record = ('first', a: 2, b: true, 'last'); //Record type annotations are comma-delimited lists of //types enclosed in parentheses. // Returns multiple values in a record: (String, int) userInfo(Map json) { return (json['name'] as String, json['age'] as int); } final json = { 'name': 'Dash', 'age': 10, 'color': 'blue', }; // Destructures using a record pattern: var (name, age) = userInfo(json); /* Equivalent to: var info = userInfo(json); var name = info.$1; var age = info.$2; */

Slide 7

Slide 7 text

Feature #3 Patterns

Slide 8

Slide 8 text

Patterns are a syntactic category in the Dart language, like statements and expressions. A pattern represents the shape of a set of values that it may match against actual values. They let you match and destructure values. This makes it easier to work with complex data structures. What are Patterns? Patterns

Slide 9

Slide 9 text

///Many patterns make use of subpatterns, sometimes called ///outer and inner patterns const a = '1'; const b = '2'; switch (obj) { // List pattern [a, b] matches obj first if obj is a list with two fields, // then if its fields match the constant subpatterns 'a' and 'b'. case [a, b]: print('$a, $b'); } ///Destructuring var numList = [1, 2, 3]; // List pattern [a, b, c] destructures the three elements from numList... var [a, b, c] = numList; // ...and assigns them to new variables. print(a + b + c);

Slide 10

Slide 10 text

/// Variable declaration // Declares new variables a, b, and c. final (a, [b, c]) = ('str', [1, 2]); ///Why use patterns? //Without patterns, validation is verbose: var json = { 'user': ['Lily', 13] }; if (json is Map && json.length == 1 && json.containsKey('user')) { var user = json['user']; if (user is List && user.length == 2 && user[0] is String && user[1] is int) { var name = user[0] as String; var age = user[1] as int; print('User $name is $age years old.'); } } //Validating incoming JSON var json = { 'user': ['Lily', 13] }; var {'user': [name, age]} = json;

Slide 11

Slide 11 text

Coming soon… Other feature releases

Slide 12

Slide 12 text

● Sound null safety ● Class modifiers Coming soon

Slide 13

Slide 13 text

Feature #1 Sound null safety

Slide 14

Slide 14 text

Sound null safety is a feature in Dart that prevents null pointer exceptions at runtime. It does this by making all variables non-nullable by default. This means that if you try to assign a null value to a variable, the compiler will throw an error. Sound null safety is a major improvement over the previous null safety model in Dart, which allowed variables to be nullable by default. What is sound null safety? Sound null safety

Slide 15

Slide 15 text

Feature #4 Class modifiers

Slide 16

Slide 16 text

Only the base modifier can appear before a mixin declaration. The modifiers do not apply to other declarations like enum, typedef, or extension ● abstract ● base ● final ● interface ● sealed ● mixin Features

Slide 17

Slide 17 text

/// ====>>>>>>> abstract classes ///To define a class that doesn’t require a full, concrete implementation of its ///entire interface, use the abstract modifier. ///Abstract classes cannot be constructed from any library, whether its own or ///an outside library. Abstract classes often have abstract methods. // Library a.dart abstract class Vehicle { void moveForward(int meters); } // Library b.dart import 'a.dart'; // Error: Cannot be constructed Vehicle myVehicle = Vehicle(); // Can be extended class Car extends Vehicle { double distance = 0.0; @override void moveForward(int meters) { // ... } }

Slide 18

Slide 18 text

///=======>>>>>>>>> base ///To enforce inheritance of a class or mixin’s implementation, ///use the base modifier. A base class disallows implementation ///outside of its own library. // Library a.dart base class Vehicle { void moveForward(int meters) { // ... } } // Library b.dart import 'a.dart'; // Can be constructed Vehicle myVehicle = Vehicle(); // Can be extended base class Car extends Vehicle { int passengers = 4; // ... } // ERROR: Cannot be implemented base class MockVehicle implements Vehicle { @override void moveForward() { // ... } }

Slide 19

Slide 19 text

///=======>>>>>>>> interface ///To define an interface, use the interface modifier. ///Libraries outside of the interface’s own defining library can ///implement the interface, but not extend it. // Library a.dart interface class Vehicle { void moveForward(int meters) { // ... } } // Library b.dart import 'a.dart'; // Can be constructed Vehicle myVehicle = Vehicle(); // ERROR: Cannot be inherited class Car extends Vehicle { int passengers = 4; // ... } // Can be implemented class MockVehicle implements Vehicle { @override void moveForward(int meters) { // ... } }

Slide 20

Slide 20 text

///===========>>>>>>sealed ///To create a known, enumerable set of subtypes, use the sealed modifier. /// This allows you to create a switch over those subtypes that is statically ///ensured to be exhaustive. sealed class Vehicle {} class Car extends Vehicle {} class Truck implements Vehicle {} class Bicycle extends Vehicle {} // ERROR: Cannot be instantiated Vehicle myVehicle = Vehicle(); // Subclasses can be instantiated Vehicle myCar = Car(); String getVehicleSound(Vehicle vehicle) { // ERROR: The switch is missing the Bicycle subtype or a default case. return switch (vehicle) { Car() => 'vroom', Truck() => 'VROOOOMM', }; }

Slide 21

Slide 21 text

///=======>>>>> final ///This prevents subtyping from a class outside of the current library. ///Disallowing both inheritance and implementation prevents subtyping entirely // Library a.dart final class Vehicle { void moveForward(int meters) { // ... } } // Library b.dart import 'a.dart'; // Can be constructed Vehicle myVehicle = Vehicle(); // ERROR: Cannot be inherited class Car extends Vehicle { int passengers = 4; // ... } class MockVehicle implements Vehicle { // ERROR: Cannot be implemented @override void moveForward(int meters) { // ... } }

Slide 22

Slide 22 text

///===========> mixins ///Mixins are a way of defining code that can be reused in multiple ///class hierarchies. They are intended to provide member implementations en masse. mixin Musical { bool canPlayPiano = false; bool canCompose = false; bool canConduct = false; void entertainMe() { if (canPlayPiano) { print('Playing piano'); } else if (canConduct) { print('Waving hands'); } else { print('Humming to self'); } } } To use a mixin, use the with keyword followed by one or more mixin names. class Musician extends Performer with Musical { // ··· entertainMe(); }

Slide 23

Slide 23 text

You can combine some modifiers for layered restrictions. A class declaration can be, in order: 1. (Optional) abstract, describing whether the class can contain abstract members and prevents instantiation. 2. (Optional) One of base, interface, final or sealed, describing restrictions on other libraries subtyping the class. 3. (Optional) mixin, describing whether the declaration can be mixed in. 4. The class keyword itself. You can’t combine some modifiers because they are contradictory, redundant, or otherwise mutually exclusive: ● abstract with sealed. A sealed class is always implicitly abstract. ● interface, final or sealed with mixin. These access modifiers prevent mixing in. Combining modifiers Class modifiers

Slide 24

Slide 24 text

“To build the most productive programming language for building fast apps on any platform” Dart long-term vision

Slide 25

Slide 25 text

Thank You Bright Etornam Sunu He/Him GDE Flutter & Dart Mobile Engineer @_iamEtornam