DEV Community

Cover image for Null Safety In Dart
Prince Srivastava
Prince Srivastava

Posted on

Null Safety In Dart

Null safety is something implemented in many languages till now. In Dart it is coming with a next level.

What is Null Safety ?

The basic goal with Null Safety is to avoid null reference exceptions at runtime. Instead all these errors will be shown at compile time.
1.So it will provide you a better development environment with less runtime errors.
2.Since errors will be pushed forward during compile time, we can use it to optimize our code.
3.It will generate smaller code because we will remove null checks like if(something != null).
4.It will make sure that wherever we are using null, we are using it safely.

Let's see some code

Go ahead and open 2 tabs with following links to see the difference
https://dartpad.dev/
https://nullsafety.dartpad.dev/
and copy this code in both the pads-

void main() {
  print(serveCoffee('ice'));  
}

String serveCoffee(String coffeeType) {
  return coffeeType + ' coffee';
}

In the above example we are passing a coffee type into the serveCoffee() method. Now we have 2 versions of DartPad open. One with null safety enabled and the other without null safety.
Instead of passing 'ice' pass null when calling the method And Notice the change -

print(serveCoffee(null));

The null safety dartpad will give you an error while the traditional dartpad won't.
Let's close the old dart pad and code in the nullsafety dartpad
So that's cool. Let's see something even better.
Make the argument coffeeType an optional argument.

String serveCoffee([String coffeeType]) { // coffeeType is now an optional argument
  return coffeeType + ' coffee';
}
void main() {
  print(serveCoffee('ice'));
  print(serveCoffee()); // here coffeeType will be null
}

Since we declared datatype of coffeeType as String, the null safety check will give an error on line 1.

Error Image

But Wait What if we want null values in optional parameters ???
We change the String type in parameter to allow null and we do it this way --

 String serveCoffee([String? coffeeType])

Doing this will give you an error on line 2 as
Alt Text

Wait Wait Wait! This is just getting interesting.

In above code you are telling the compiler that you will handle the null case by yourself. BUT you have not done so.

So, let's handle the null case.

String serveCoffee([String coffeeType]) {
 if(coffeeType == null) {
  return 'hot coffee';
 }
 return coffeeType + ' coffee';
}
void main() {
  print(serveCoffee('ice'));
  print(serveCoffee());
}

BOOM! The error is gone because now the compiler knows that you have handled the null case and the code will not go beyond the if statement.

What to do if we know that the value won't be null ??

Definitely we don't want to use the redundant if statement...
We will use the bang operator(!) instead.

String serveCoffee([String? coffeeType]) {
 return coffeeType! + ' coffee';
}
void main() {
  print(serveCoffee('ice'));
  print(serveCoffee()); // This will give error on runtime.
}

Here we are telling the compiler that we will not pass any null value to the optional argument.

How do we do this for class variables ?

Suppose we have the following code and we know setHot() method will always be called before serve() method.
But how do we tell this to the compiler ???

class Coffee {
 String _coffeeType;


  void setHot() {
    _coffeeType = 'Hot ';
  }

  String serve() => _coffeeType + 'Coffee';

}

When the compiler checks the above code statically, it sees that _coffeeType is not initialized and can be null in the serve() method, so it gives an error.

How do we fix that ??

There are 3 possible ways and let's get started with the simplest one.
We will initialise _coffeeType in the class constructor:

class Coffee {
 String _coffeeType;
 Coffee(): _coffeeType= 'Cold';

  void setHot() {
    _coffeeType = 'Hot ';
  }

  String serve() => _coffeeType + 'Coffee';

}

The error is gone because now the compiler knows that it won't be null.

2nd way is to make _coffeeType a nullable String and use the bang operator

class Coffee {
 String? _coffeeType;

  void setHot() {
    _coffeeType = 'Hot ';
  }

  String serve() => _coffeeType! + 'Coffee'; // bang operator

}

Here comes the new player 'late' keyword

class Coffee {
 late String _coffeeType;

  void setHot() {
    _coffeeType = 'Hot ';
  }

  String serve() => _coffeeType + 'Coffee';

}

Now we are telling the compiler to not check it statically and see it at runtime.
Note if you pass a null value it will give a runtime exception.

That's all from my side on null safety in dart.

You can explore it even further on the null safety dart pad where on the top right corner you have an option of learning with snippets.

Alt Text

Do let me know your thoughts on this in the comments below ...

Top comments (2)

Collapse
 
ishansrivastava profile image
Ishan Srivastava

This is awesome. Thanks for sharing 👍

Collapse
 
pr1 profile image
Prince Srivastava

Thanks Sir 😁