The curious case of void in Dart
I think the
void type is the most curious and subtle type in Dart. As of now, I have got enough experience with Dart that I’m able to explore almost every topic in Dart. But guess what, it surprises me like always. Whenever I began to think that now I have explored all the major parts of the language, it hits me in the head with a brick. At first, it seemed frustrating and difficult to grasp, I tried searching about
void on the official docs and all other places on the internet that could solve my problem but what I found was just this article which opens when you click on the
void keyword on the official docs. Since most of my programming days are passed with Java and Android, and Dart is almost similar to Java in comparison to syntax but in some places, it just takes another path far from the way Java does it.
😯 What Confuses about void in Dart?
If you are coming from Java or some other similar programming language then probably you are comfortable with the thing that method or function with return type
void doesn’t returns anything. But in Dart that doesn’t works and
void is not that simple to grasp.
Initially lets see how
void return type behaves in java:
MyVoid is a simple class which contains a method
show with return type
void . Since the return type is
void the method prints Good Morning World!! and exits without returning anything. I think things are pretty clear right away but now we will look at how Dart handles
Note: Every function in Dart returns a value, if you are not declaring it explicitly then null will be returned by default.
In the above program either we can return something or we can leave it, if we do not return anything then by default null is returned.
What we are doing here is declaring a top level method
show with return type
void which is called in the
main method, one thing that you should focus on is
show method is returning
Function and we are allowed to do some more stuff with Function like :
- Declare it as a parameter
- Pass it as an argument
- Assign it to a variable
- Return a function from a function
- Return a result of a function from a function (This is what we are doing above)
So, now you must understand that Dart functions are no ordinary methods, in fact they are functions on steroid. Now returning to our code above, inside
show method we are first executing the method
Note: The return type only specifies what the DartAnalyzer warns you about. There are type checks now in Dart2 that also check that at runtime.
If the return type of
show function is
void then only three things can be returned, returning any other result will cause a type warning.
1 ) Return null
2 ) Return dynamic variable
3 ) Return void function
But even if Dart allows to return these three things in a void function, it doesn’t allow us to use these returned values from a
For example the code below will not compile:
Because Dart doesn’t allow us to use the values returned by
void functions. Once we change the return type of the
show method, we can use the value returned by the method.
value = null , do you know why?
show method we are executing
Good Morning World. If no value is explicitly returned, then
null is returned.
null is (or would also be) returned when the return type of
show is void, but Dart refuses to compile so it doesn’t come to that.
😑 Things are more chaotic when we use Shorthand Function () =>
Can you guess Is the above program valid or not?
The program will compile without any error and it is 100% valid. If you guessed it then congrats and if not then don’t think too much about it, as it happened with me also. Yes you can ask that the return types are
void then how can we return
bool or a
function ? So the answer is you can return anything from a shorthand function with return type
void but guess what? You can’t communicate with or use those returned values in any way.
So why is returning everything allowed through a shorthand function[()=>] even if the return type is void?
As we have discussed above in normal functions with return type
void we can only return three types of values(i.e
dynamic) but in shorthand function things are little different because shorthand functions always returns a value and if we limit the values that could be returned then functions with
void return types will become invalid. Lets take an example of setter function as the default return type of every setter is void and they are often declared as a shorthand function.
If you have learned Dart then probably you know that every instance variable in Dart has a getter and setter implicitly. Indeed Dart gives some extra privilege to getter and setter methods treating them like special methods.Look at the code below, here we are setting value to library private instance variable
_val using a setter —
Setter are declared using the keyword
set in Dart and their return type must be
void or absent. If it is absent it is
void implicitly. And remember every shorthand function implicitly declares the return keyword, which means you don’t have to declare return keyword instead it is automatically added in the shorthand function. The expression
_val = val is an assignment expression and it returns the value assigned. If shorthand functions are not designed in such a way that it allows all types of values to be returned by
void then the setter methods will become invalid. You can think of it as a kind of settlement and their’s fair number of discussion going on the topic inside Dart community. Also Dart is an evolving language so you can expect things can change in near future.(and may be not in this case)
☀️ One more thing!
Until Dart 1
void is only usable as a return types of functions (like
void main() ) but from Dart 2(along with static checking, runtime type safety, optional new/const, core library improvements, and more),
void has also been generalized. So what does that mean? 🤔
Dart gives a very gentle way to handle asynchronous code that looks very similar to the synchronous code. I personally like this feature very much. When we are working with Futures , there are many situations when we don’t want to get a result when our asynchronous work is done. Before Dart 2 we have to use
Future<Null> for this but ever since the release of Dart 2, things are better , as now we can do it like this
Here I don’t want anything to be returned after the
cache is cleared so we are using
void as a type parameter. Also we can almost achieve the same thing with
void was not allowed in Dart 1 as generic type parameter and that’s why
Future<Null> was used for that purpose.There could be whole lot of other things which we can discuss about them but for now just keep in mind that
void will allow to return any value but you can’t use or communicate with the values returned(if you try to do so, you will get a warning) and
Null only allows to return
Thanks for reading. If you liked this one, you should follow me for the next one. 🙏
Thank You Günter Zöchbauer for the Proofreading and for all the awesome work you are doing on Stackoverflow for the Dart Community.
If you have any questions, feel free to post them 👇.
Any feedback is welcome 😃.