avatarMehmet Yaz

Free AI web copilot to create summaries, insights and extended knowledge, download it at here

4635

Abstract

s from certain people:</p><div id="b727"><pre>Person mother <span class="hljs-operator">=</span> Person(//) mother.talk()<span class="hljs-comment">;</span></pre></div><p id="dbc4">If we are thinking about a certain person, we must have created an <b>instance</b> <b>of ‘Person’</b> for that person in our minds (or RAM in a Computer).</p><h1 id="43d8">3—Class Fields</h1><p id="3eca">As we have mentioned above, these common names defined in our minds have some features like person’s age, name.</p><p id="5352"><b>This is where null safety comes into play.</b></p><p id="02cb">Of course, there may be thousands of classes related to a person in our minds or universe’s code. “Newly Met Person”, “My Friend” etc.</p><p id="c414">But let’s simplify this quite a bit. And suppose we have only one definition of Person in our minds and a few properties like age, name etc.</p><p id="08ba">A quick question for you? While meeting a person, when you ask his/him age, have you ever thought of a question : “I wonder if this person has an age?”. Or when you ask someone their age, “I don’t have one.” Do you expect an answer like that?</p><p id="f4b3">If no, <code>int age;</code> can <b>NEVER</b> be nullable in universe’s code.</p><blockquote id="a7fd"><p>Maybe we haven’t asked someone’s age yet, or he/she hasn’t said it. But in reality, we don’t need a person’s age to form in our minds. So let’s pretend we know everything we can know(in the moment and future) and we need in our case.</p></blockquote><p id="548d">Another question is:</p><p id="4a81">When we ask a person the question “where do you work”, do you always get a workplace information in the answer?</p><p id="60ef">If no, our <code>jobID</code> class member is <b>nullable</b>. Not everyone has to have a job.</p><p id="f44a">Yes, now let’s define a class with these two properties:</p><figure id="a61f"><img src="https://cdn-images-1.readmedium.com/v2/resize:fit:800/1*8E5Xt1ie176KE-ap6AIyGQ.png"><figcaption></figcaption></figure><p id="8026">This means that a person may have a <code>jobID</code>, maybe not. But he/she definitely has <code>age</code>.</p><p id="16cb">Now you have encountered an error here. Do you think it is right to break the logical context we mentioned above about age and job ID to solve this error?</p><p id="a5d5">Here the <code>int? age</code> solution breaks our logical context.</p><p id="2159">So what is the error and how to solve it?</p><p id="cdda">Let’s handle the wrong solutions first:</p><p id="c180">1- Make Nullable.</p><p id="a702">We’ve already mentioned this: age cannot be null. So this is not a solution.</p><p id="1670">2- Add <code>late</code> modifier.</p><p id="fbeb">In most cases this is not the right solution either. Persons have an age from the moment they exist.</p><p id="d3c3">3- Give a default age.</p><p id="e087"><code>int age = 0;</code>. If you think that every person you see/ meet/ know is a newborn, possibly it’s a good solution. The fact that its age is not yet known in your mind (that is, when a person instance has not yet formed) does not mean that the person age is zero.</p><p id="8dcd"><b>Solution</b></p><p id="e84a">As you can see, we used words like “yet”, “not yet” and “moment” a lot. Existence, the process of existence and its chronology have an important place.</p><p id="376e">So let’s take a quick look at how an instance is created.</p><p id="2e0b">Now we are defining and creating a Person class/instance for a conversation.</p><p id="9c40">Let’s take a look at the example below and see in what order they work.</p><figure id="2594"><img src="https://cdn-images-1.readmedium.com/v2/resize:fit:800/1*lLXdolSz3dwGhrwuXDYv1w.png"><figcaption></figcaption></figure><p id="5fb0">These concepts will be used:</p><blockquote id="39c8"><p>SpokenPerson(<params>) : <final-initializer>{<construction-body>}</construction-body></final-initializer></params></p></blockquote><p id="26c5">So:</p><p id="7048">1 — <b>Before Executing Construct.</b></p><p id="824b">First, let’s consider what we can actually know before a SpokenPerson is created : That our conversation duration is 0. All the others are things we will never know before we create this person in our minds.</p><blockquote id="be23"><p>Notice, everything known before is not <code><i>static</i></code>. The conversation Duration Ms is about a specific SpokesPerson instance. Static properties are properties that are not specific to a certain object instance.</p></blockquote><p id="d1dc">When we want to create an instance using the SpokenPerson(…) expression, “conversationDurationInMs = 0” (as setter) will run first.</p><p i

Options

d="5014">2 — <b><params></b></p><p id="33df">We need information to create a SpokenPerson instance. So the <params> part works. The parameters here are read, if any, default values are taken. “this.” or “super.” statements are actually the first part of the next stage<final-initializer>. We can only use it in this stage for coding convenience.</final-initializer></params></p><p id="8d0f">As a result, this stage is where the necessary questions are asked and the necessary preparations are made to create a SpokenPerson instance.</p><p id="c906">3 — <b><final-initializer></b></p><p id="e41c">This stage is the creation stage of an object. The object has not yet been formed at this stage. Like an embryo.</p><p id="a0f5">As soon as this stage is over, the object will be created. This means that at the end of this stage we need to know all the final variables and required variables associated with an object. If there is information concerning the superior object, it must be given here with super’s constructor.</p><p id="ba6e">The main reason for our error above is that “age” is unknown at or before this stage.</p><p id="87d6">Here, we can’t access instance members.</p><p id="c2e9">4 — <code><b>late</b></code><b> modifier with value members.</b></p><p id="d2b0">This is the stage that works between <code><final-initializer></code> and <code><construction-body></code>. The section below represents this stage. Here we can access instance members. But what we can value from this point forward does not mean that the value will definitely be given here. The value is given the first time we use a <code>late </code>instance member.</p><p id="6e3d"><code>late bool tallerThanMe = height > 1.78;</code></p><p id="236d">5 — <b><construction-body></b></p><p id="a82c">This stage is the stage where the actions to be performed immediately after the object is created. Here we can access instance members.</p><p id="d212">In this example, we talk to it right after creating an instance.</p><p id="6dba">6 — <b>set late members</b></p><p id="75c6">If it exists, and we are setting it, we set the late members at the end (at an indefinite time).</p><p id="33e7"><code>satisfiedWithConversation</code>. We cannot ask this before we speak. We’ll know after we talk. But unlike nullable ones, we can know for sure after talking.</p><h2 id="e0f6">Solution Result</h2><p id="4eb7">1 — If a property is not going to be null in our case, we <b>never </b>make it nullable. Request them as parameters or calculate and give values, latest in the final-initializer.</p><p id="fecc">2 — If you have a non-nullable member, but its value is not known yet when the instance is created, use <code>late</code>. Only use it when you’re sure you’ll appreciate it before using it.</p><p id="825d">3 — “Does it have this feature?” If you answer “sometimes” to the question, set it to nullable. And always ask if it’s an existing condition before using it (check null).</p><h1 id="1766">Some Tips</h1><h2 id="3437">late with instance member</h2><p id="1ea1">A member with a late modifier can access instance members. In the example, “widget” is an instance member (owned by State) and we can access it. This is functionally like valuing currentTitle in initState. However, the fact that we can value the currentTitle variable immediately after the instance is created does not mean that it will be given a certain value exactly after construct. The first time we use a late member, it is given its value.</p><p id="7579">So, any attempt to read this late variable before “State” attaches to the widget will result in an <b>error</b>.</p><p id="4b23">That’s my own policy, but I think it’s functional: Don’t use <code>late</code> with value.</p><p id="5be8">WRONG WAY:</p><figure id="c85d"><img src="https://cdn-images-1.readmedium.com/v2/resize:fit:800/1*7Q3Lu0vmTb2RU_wvOX5_4Q.png"><figcaption></figcaption></figure><h2 id="30f6">Need an initialize/attach</h2><p id="16d1">If one of your controller requires an initialize function, or if an instance of a class works together with an instance of another class (State-StatefulWidget, Widget-Element, Controller-Client), a structure that facilitates access to this connected/attached instance can be established.</p><figure id="c111"><img src="https://cdn-images-1.readmedium.com/v2/resize:fit:800/1*_eyjhdxmlZZy9QoqoERcUw.png"><figcaption></figcaption></figure><p id="c07b">Depending on the situation, if a change is expected, check the <code>hasClient</code>and then use the <code>client </code>comfortably. Equivalent in State <code>mounted</code>.</p></article></body>

Really Null Safety in Flutter/Dart

Dear Dart developers, beginners or professionals, I think, it is time to truly understand and assimilate null-safety.

I see these misunderstandings over and over in many questions asked in the communities and in the work of beginner developers, and I do my best to correct them. I even feel sorry for beginners when I see that null-safety is still not well understood in many tutorial code snippets created by professionals.

Lots of developers inspired by these code snippets then have a hard time taking the right approach. I also think old answers on Stack Overflow or old videos on YouTube have a big influence on this too.

Null-safety Extra work or Convenience?

Is null-safety a penalty for adding extra symbols like “?” or “!” ?

Is null safety just a tool that gives more compile time/runtime errors ?

Of course no. On the contrary, null safety saves us from unnecessary symbols and offers us safer coding.

One of the first situations someone who doesn’t understand null-safety will encounter is: Defines a class member and gets an error: “Non-nullable instance field ‘x’ must be initialized.”

The developer implements two possible solutions to this error:

This solution is mostly a DISASTER. In reality, it is never a solution.

This solution is just an extra (unnecessary) ? or “ = "" ”, and then an extra ! in usage.

Now listen carefully to get rid of these extra workloads!

In this article, I will explain null safety, inspired by the real life outside the code, the uses in the code and the approach of the human mind.

This article will also serve as a guide that systematizes the path I will follow while explaining it to the beginner developers in my network.

1- Logical Context

First, we will examine the subject discussed in this article in the logical context, not only in terms of uses in Dart code. In most cases, any definition that doesn’t fit into logical context makes it harder to work as a team (even if it means a shorter code snippet), distracting us from flexible coding.

So we’re not going to learn things like “don’t get/fix the error”, “write shorter code”, “usually used approaches/methods” now.

We will now look at how null-safety works in real life (in neurons in our brain). We will become aware of what our brain is constantly doing. Thus, we will use this awareness while coding.

Now, let’s clarify our approach on the most important issue concerning null safety: Class

2- What is class?

This is not a tutorial on classes. I just want you to see how we’re going to approach the issue.

In my approach, a class is a common noun. Creating a class can be called defining/learning a common name.

For example, when we are babies, we learn these common names with questions such as what is a person, what is a toy, what is a city, and their answers. Of course, if the universe were a code. These were defined much earlier.

The code equivalent of what we have in mind in this learning process is:

class Person {
   //…
}
class Toy {
    //…
}
class City {
    //…
}

Later we learn that every person has an age and people talk:

class Person {
    //…
    int age;
    void talk() {
        //…
    }
}

As a common noun, people talk, but we hear these conversations from certain people:

Person mother = Person(/*…*/)
mother.talk();

If we are thinking about a certain person, we must have created an instance of ‘Person’ for that person in our minds (or RAM in a Computer).

3—Class Fields

As we have mentioned above, these common names defined in our minds have some features like person’s age, name.

This is where null safety comes into play.

Of course, there may be thousands of classes related to a person in our minds or universe’s code. “Newly Met Person”, “My Friend” etc.

But let’s simplify this quite a bit. And suppose we have only one definition of Person in our minds and a few properties like age, name etc.

A quick question for you? While meeting a person, when you ask his/him age, have you ever thought of a question : “I wonder if this person has an age?”. Or when you ask someone their age, “I don’t have one.” Do you expect an answer like that?

If no, int age; can NEVER be nullable in universe’s code.

Maybe we haven’t asked someone’s age yet, or he/she hasn’t said it. But in reality, we don’t need a person’s age to form in our minds. So let’s pretend we know everything we can know(in the moment and future) and we need in our case.

Another question is:

When we ask a person the question “where do you work”, do you always get a workplace information in the answer?

If no, our jobID class member is nullable. Not everyone has to have a job.

Yes, now let’s define a class with these two properties:

This means that a person may have a jobID, maybe not. But he/she definitely has age.

Now you have encountered an error here. Do you think it is right to break the logical context we mentioned above about age and job ID to solve this error?

Here the int? age solution breaks our logical context.

So what is the error and how to solve it?

Let’s handle the wrong solutions first:

1- Make Nullable.

We’ve already mentioned this: age cannot be null. So this is not a solution.

2- Add late modifier.

In most cases this is not the right solution either. Persons have an age from the moment they exist.

3- Give a default age.

int age = 0;. If you think that every person you see/ meet/ know is a newborn, possibly it’s a good solution. The fact that its age is not yet known in your mind (that is, when a person instance has not yet formed) does not mean that the person age is zero.

Solution

As you can see, we used words like “yet”, “not yet” and “moment” a lot. Existence, the process of existence and its chronology have an important place.

So let’s take a quick look at how an instance is created.

Now we are defining and creating a Person class/instance for a conversation.

Let’s take a look at the example below and see in what order they work.

These concepts will be used:

SpokenPerson() : {}

So:

1 — Before Executing Construct.

First, let’s consider what we can actually know before a SpokenPerson is created : That our conversation duration is 0. All the others are things we will never know before we create this person in our minds.

Notice, everything known before is not static. The conversation Duration Ms is about a specific SpokesPerson instance. Static properties are properties that are not specific to a certain object instance.

When we want to create an instance using the SpokenPerson(…) expression, “conversationDurationInMs = 0” (as setter) will run first.

2 — <params>

We need information to create a SpokenPerson instance. So the part works. The parameters here are read, if any, default values are taken. “this.” or “super.” statements are actually the first part of the next stage. We can only use it in this stage for coding convenience.

As a result, this stage is where the necessary questions are asked and the necessary preparations are made to create a SpokenPerson instance.

3 — <final-initializer>

This stage is the creation stage of an object. The object has not yet been formed at this stage. Like an embryo.

As soon as this stage is over, the object will be created. This means that at the end of this stage we need to know all the final variables and required variables associated with an object. If there is information concerning the superior object, it must be given here with super’s constructor.

The main reason for our error above is that “age” is unknown at or before this stage.

Here, we can’t access instance members.

4 — late modifier with value members.

This is the stage that works between <final-initializer> and <construction-body>. The section below represents this stage. Here we can access instance members. But what we can value from this point forward does not mean that the value will definitely be given here. The value is given the first time we use a late instance member.

late bool tallerThanMe = height > 1.78;

5 — <construction-body>

This stage is the stage where the actions to be performed immediately after the object is created. Here we can access instance members.

In this example, we talk to it right after creating an instance.

6 — set late members

If it exists, and we are setting it, we set the late members at the end (at an indefinite time).

satisfiedWithConversation. We cannot ask this before we speak. We’ll know after we talk. But unlike nullable ones, we can know for sure after talking.

Solution Result

1 — If a property is not going to be null in our case, we never make it nullable. Request them as parameters or calculate and give values, latest in the final-initializer.

2 — If you have a non-nullable member, but its value is not known yet when the instance is created, use late. Only use it when you’re sure you’ll appreciate it before using it.

3 — “Does it have this feature?” If you answer “sometimes” to the question, set it to nullable. And always ask if it’s an existing condition before using it (check null).

Some Tips

late with instance member

A member with a late modifier can access instance members. In the example, “widget” is an instance member (owned by State) and we can access it. This is functionally like valuing currentTitle in initState. However, the fact that we can value the currentTitle variable immediately after the instance is created does not mean that it will be given a certain value exactly after construct. The first time we use a late member, it is given its value.

So, any attempt to read this late variable before “State” attaches to the widget will result in an error.

That’s my own policy, but I think it’s functional: Don’t use late with value.

WRONG WAY:

Need an initialize/attach

If one of your controller requires an initialize function, or if an instance of a class works together with an instance of another class (State-StatefulWidget, Widget-Element, Controller-Client), a structure that facilitates access to this connected/attached instance can be established.

Depending on the situation, if a change is expected, check the hasClientand then use the client comfortably. Equivalent in State mounted.

Flutter
Null Safety
Dart
Dartlang
Flutter Null Safety
Recommended from ReadMedium