Chapter 4

Hello Again

IN THIS CHAPTER

check Looking at functions in a Flutter app

check Learning to type

check Dealing with variables and other little things

♪ “Hello, hello again, sh-boom and hopin’ we’ll meet again.” ♪

— JAMES KEYES, CLAUDE FEASTER, CARL FEASTER, FLOYD F. MCRAE, AND JAMES EDWARDS, SUNG BY THE CHORDS, THE CREW-CUTS, STAN FREBERG, AND OTHERS, 1954

Chapter 3 is all about a simple Hello world program. For convenience, I copy one version of the code here, in Listing 4-1.

LISTING 4-1 Yet Another Look at the First Hello Program

import 'package:flutter/material.dart';
 
main() => runApp(App0401());
 
class App0401 extends StatelessWidget {
Widget build(BuildContext context) {
return MaterialApp(
home: Material(
child: Center(child: Text("Hello world!")),
),
);
}
}

In Chapter 3, I have you concentrate on the middle of the program — the MaterialApp and all the stuff inside it. I let you gleefully ignore the other parts of the program. In particular, I let you ignore anything having to do with things called “functions.” This chapter continues the tour of a Hello World program and sets its sites on those “function” things.

Creating and Using a Function

Here’s an experiment: Run the app whose code is shown in Listing 4-2.

LISTING 4-2 Words, Words, Words

import 'package:flutter/material.dart';
 
main() => runApp(App0402());
 
class App0402 extends StatelessWidget {
Widget build(BuildContext context) {
return MaterialApp(
home: Material(
child: Center(child: Text(highlight("Look at me"))),
),
);
}
}
 
highlight(words) {
return "*** " + words + " ***";
}

Remember You can download this app’s code (and the code for every other listing in this book) from my website. The URL is https://allmycode.com/Flutter.

Figure 4-1 shows you the output of the app in Listing 4-2.

Snapshot of another exciting Flutter app.

FIGURE 4-1: Another exciting Flutter app.

Listing 4-2 contains a function declaration and a function call. (See Figure 4-2.)

Snapshot of the ighlight function in Listing 4-2.

FIGURE 4-2: The highlight function in Listing 4-2.

The function declaration

Think about a recipe — a set of instructions for preparing a particular meal. A function declaration is like a recipe: It’s a set of instructions for performing a particular task. In Listing 4-2, this set of instructions says, “Form the string containing asterisks followed by some words followed by more asterisks, and return that string somewhere.”

Most recipes have names, like Macaroni and Cheese or Triple Chocolate Cake. The function at the bottom of Listing 4-2 also has a name: Its name is highlight. (See Figure 4-3.) There’s nothing special about the name highlight. I made up the name highlight all by myself.

Snapshot of a header and a body.

FIGURE 4-3: A header and a body.

Tip In Figure 4-3, the function name highlight is in the part of the declaration called the header. The function’s instructions (return "*** " + words + " ***") are in the part of the declaration called the body.

A recipe for macaroni and cheese sits in a book or on a web page. The recipe doesn’t do anything. If no one uses the recipe, the recipe lies dormant. The same is true of a function declaration. The declaration in Listing 4-2 doesn’t do anything on its own. The declaration just sits there.

A function call

Eventually, somebody might say, “Please make macaroni and cheese for dinner,” and then someone follows the Macaroni and Cheese recipe’s instructions. One way or another, the process begins when someone says (or maybe only thinks) the name of the recipe.

A function call is code that says, “Please execute a particular function declaration’s instructions.” Imagine a phone or another device that’s running the code in Listing 4-2. When the phone encounters the function call highlight("Look at me"), the phone is diverted from its primary task — the task of constructing an app with its Material, Center, and Text widgets. The phone takes a detour to execute the instructions in the highlight function’s body. After figuring out that it should create "*** Look at me ***", the phone returns to its primary task, adding the Text widget with "*** Look at me ***" to the Center widget, adding the Center widget to the Material widget, and so on.

A function call consists of a function’s name (such as the name highlight in Listing 4-2), followed by some last-minute information (such as "Look at me" in Listing 4-2).

Wait! In the previous sentence, what does some last-minute information mean? Read on.

Parameters and the return value

Suppose that your recipe for macaroni and cheese serves one person and calls for two ounces of uncooked elbow macaroni. You’ve invited 100 people to your intimate evening gathering. In that case, you need 200 ounces of uncooked elbow macaroni. In a way, the recipe says the following: “To find the number of ounces of uncooked elbow macaroni that you need, multiply the number of servings by 2.” That number of servings is last-minute information. The person who wrote the recipe doesn’t know how many people you’ll be serving. You provide a number of servings when you start preparing the mac-and-cheese. All the recipe says is to multiply that number by 2.

In a similar way, the highlight function declaration in Listing 4-2 says, “To find the value that this function returns, combine asterisks followed by the words that you want to be highlighted followed by more asterisks.”

A function declaration is like a black box. You give it some values. The function does something with those values to calculate a new value. Then the function returns that new value. (See Figures 4-4 and 4-5.)

Snapshot of a function declaration that is like a black box.

FIGURE 4-4: Good stuff in, good stuff out.

Snapshot of the function to calculate a new value and returning that new value.

FIGURE 4-5: In with the old, out with the new.

Figures 4-4 and 4-5 show what it means to give values to a function, and for a function to return a value.

  • You give values to a function with the function’s parameter list.

    Like any constructor call, every function call has a parameter list. Each parameter feeds a piece of information for the function to use. In Figure 4-5, the function call highlight("Look at me") passes the value "Look at me" to the highlight function’s declaration. Inside the function declaration, the name words stands for "Look at me", so the expression "*** " + words + " ***" stands for "*** Look at me ***".

  • You return a value from a function with a return statement.

    In Listing 4-2, the line

    return "*** " + words + " ***";

  • is a return statement. Again, imagine a phone that’s running the code in Listing 4-2. With the execution of this return statement, this is what happens:
    • The phone stops executing any code inside the body of the highlight function.
    • The phone replaces the entire function call with the returned value so that

      Center(child: Text(highlight("Look at me")))

      effectively becomes

      Center(child: Text("*** Look at me ***"))

    • It continues to execute whatever code it was executing before it became diverted by the function call. It takes up where it left off, constructing the Center, Material, and MaterialApp widgets.

A cookbook may have only one recipe for chicken fricassee, but you can follow the recipe as many times as you want. In the same way, a particular function has only one declaration, but an app may contain many calls to that function. To see this in action, look at Listing 4-2, and change the code’s child parameter, like so:

child: Column(mainAxisAlignment: MainAxisAlignment.center, children: [
Text(highlight("Look at me")),
Text(highlight("Your attention, please"))
])

The new child contains two calls to the highlight function, each with its own parameter value. The resulting app is what you see in Figure 4-6.

Snapshot of Two Text widgets.

FIGURE 4-6: Two Text widgets.

Crossreference A return statement is only one of several kinds of statements in the Dart programming language. For more about this topic, see the section “Statements and declarations,” later in this chapter.

Tip In this chapter, I’m careful to distinguish between a function declaration and a function call. In many other chapters, I become sloppy and refer to either the declaration, the call, or both as a plain, old function. I’m not alone in this practice. Most programmers do the same thing.

Programming in Dart: The Small Stuff

“Dart is boring.” That’s what Faisal Abid said during a presentation at DevFest NYC 2017. He wasn’t talking trash about Dart. He was merely explaining that Dart is much like many other programming languages. If you’ve written some programs in Java, C++, or JavaScript, you find Dart’s features to be quite familiar. You encounter a few surprises, but not too many. When you’re learning to create Flutter apps, you don’t want a new, complicated programming language to get in your way. So, a boring language like Dart is just what you need.

This section presents some unexciting facts about the Dart programming language. Try not to fall asleep while you read it.

Statements and declarations

A statement is a piece of code that commands Dart to do something. If you think this definition is vague, that’s okay for now. Anyway, in Listing 4-2, the line

return "*** " + words + " ***";

is a statement because it commands Dart to return a value from the execution of the highlight function.

Unlike a statement, a declaration’s primary purpose is to define something. For example, the highlight function declaration in Listing 4-2 defines what should happen if and when the highlight function is called.

Statements and declarations aren’t completely separate from one another. In Listing 4-2, the highlight function declaration contains one statement — a return statement. A function declaration may contain several statements. For example, the following declaration contains three statements:

highlight2(words) {
print("Wha' da' ya' know!");
print("You've just called the highlight2 function!");
return "*** " + words + " ***";
}

The first two statements (calls to Dart’s print function) send text to Android Studio’s Run tool window. The third statement (the return statement) makes highlight("Look at me") have the value "*** Look at me ***".

Remember Use Dart’s print function only for testing your code. Remove all calls to print before publishing an app. If you don’t, you might face some trouble. At best, the calls serve no purpose and can slow down the run of your app. At worst, you may print sensitive data and show it to malicious hackers.

Dart’s typing feature

What does “five” mean? You can have five children, but you can also be five feet tall. With five children, you know exactly how many kids you have. (Unlike the average American family, you can’t have 2.5 kids.) But if you’re five feet tall, you might really be five feet and half an inch tall. Or you might be four feet eleven-and-three-quarter inches tall, and no one would argue about it.

What else can “five” mean? Nuclear power plants can undergo fire-induced vulnerability evaluation, also known as five. In this case, “five” has nothing to do with a number. It’s just f-i-v-e.

A value’s meaning depends on the value’s type. Consider three of the Dart language’s built-in types: int, double, and String.

  • An int is a whole number, with no digits to the right of the decimal point.

    If you write

    int howManyChildren = 5;

    in a Dart program, the 5 means “exactly five.”

  • A double is a fractional number, with digits to the right of the decimal point.

    If you write

    double height = 5;

    in a Dart program, the 5 means “as close to five as you care to measure.”

  • A String is a bunch of characters.

    If you use single quotes (or double quotes) and write

    String keystroke = '5';

  • in a Dart program, the ’5’ means “the character that looks like an uppercase letter S but whose upper half has pointy turns.”

A value’s type determines what you can do with that value. Consider the values 86 and "86".

  • The first one, 86, is a number. You can add another number to it.

    86 + 1 is 87

  • The second one, "86", is a string. You can’t add a number to it, but you can add another string to it.

    "86" + "1" is "861"

Remember In some languages, you can combine any value with any other value and produce some kind of a result. You can’t do that in Dart. The Dart programming language is type safe.

Literals, variables, and expressions

The Dart language has literals and variables. The value of a literal is the same in every Dart program. For example, 1.5 is a literal because 1.5 means “one-and-a-half” in every Dart program. Likewise, "Hello world!" in Listing 4-1 is a literal because "Hello world!" stands for the same string of 12 characters in every Dart program. (Yes, the blank space counts as one of the characters.)

Technical Stuff Fun fact: In early versions of FORTRAN (circa 1956), you could change the meaning of the literal 5 so that it stood for something else, like the number 6. Talk about confusing!

The value of a variable is not the same in every Dart program. In fact, the value of a variable may not be the same from one part of a Dart program to another. Take, for example, the following line of code:

int howManyChildren = 5;

This line is called a variable declaration. The line defines a variable named howManyChildren whose type is int. The line initializes that variable with the value 5. When Dart encounters this line, howManyChildren stands for the number 5.

Later, in the same program, Dart may execute the following line:

howManyChildren = 6;

This line is called an assignment statement. The line makes howManyChildren refer to 6 instead of 5. Congratulations on the birth of a new child! Is it a girl or a boy?

An expression is a part of a Dart program that stands for a value. Imagine that your code contains the following variable declarations:

int numberOfApples = 7;
int numberOfOranges = 10;

If you start with these two declarations, each entry in the left column of Table 4-1 is an expression.

TABLE 4-1 Fruitful Expressions

Expression

Value

Type

Notes

7

7

int

7.1

7.1

double

7.0

7.0

double

Even with .0, you get a double.

7.1 + 8

15.1

double

A double plus an int is a double.

0.1 + 0.1 + 0.1

0.30000000000000004

double

Arithmetic on double values isn’t always accurate.

numberOfApples

7

int

numberOfOranges

10

int

numberOfApples + numberOfOranges

17

int

Who says you can’t add apples and oranges?

8 + numberOfApples

15

int

numberOfOranges * 10

100

An asterisk (*) stands for multiplication.

20 / 7

2.857142857142857

double

A slash (/) performs division and produces a double.

20.0 ~/ 7.0

2

int

The ~/ combination performs division and produces an int. It always rounds down.

(20 / 7).round()

3

int

This is how you round up or down to the nearest int value.

20 % 7

6

int

When you divide 20 by 7, you get 2 with a remainder of 6.

highlight("Look at me")

"*** Look at me ***"

String

Assuming that you’ve declared highlight as in Listing 4-2, the function returns a Striing.

’9’ + numberOfApples.toString()

’97’

String

numberOfApples.toString() is a String. Its value is ’7’.

In the last row of Table 4-1, do you really need the toString() part? Yes, you do. If you write ’9’ + numberOfApples, you get an error message because ’9’ is a String and numberOfApples is an int. You can’t add an int value to a String value.

Remember The Dart language has statements and expressions. A statement is a command to do something; an expression is code that has a value. For example, the statement print("Hello"); does something. (It displays Hello in Android Studio’s Run tool window.) The expression 3 + 7 * 21 has a value. (Its value is 150.)

You can apply Dart’s toString to any expression. For some examples, see Chapter 7.

Tip Dart provides a quick way to determine the type of a particular expression. To see this, change the highlight function declaration in Listing 4-2 as follows:

highlight(words) {
print(20 / 7);
print((20 / 7).runtimeType);
return "*** " + words + " ***";
}

When you run the app, the following lines appear in Android Studio’s Run tool window:

flutter: 2.857142857142857
flutter: double

The value of 20 /7 is 2.857142857142857, and the value of (20 / 7).runtimeType is double.

Two for the price of one

In Dart, some statements do double duty as both statements and expressions. As an experiment, change the highlight function in Listing 4-2 so that it looks like this:

highlight(words) {
int numberOfKazoos;
print(numberOfKazoos);
print(numberOfKazoos = 94);
return "*** " + words + " ***";
}

Android Studio issues a warning that the numberOfKazoos variable isn’t used, but that’s okay. This is only an experiment. Here’s what you see in Android Studio’s Run tool window when you run this code:

flutter: null
flutter: 94

The line int numberOfKazoos; is a variable declaration without an initialization. That’s fair game in the Dart programming language.

When Dart executes print(numberOfKazoos); you see flutter: null in the Run tool window. Roughly speaking, null means “nothing.” At this point in the program, the variable numberOfKazoos has been declared but hasn’t yet been given a value, so numberOfKazoos is still null.

Finally, when Dart executes print(numberOfKazoos = 94); you see flutter: 94 in the Run tool window. Aha! The code numberOfKazoos = 94 is both a statement and an expression! Here’s why:

  • As a statement, numberOfKazoos = 94 makes the value of numberOfKazoos be 94.
  • As an expression, the value of numberOfKazoos = 94 is 94.

Of these two facts, the second is more difficult for people to digest. (I’ve known some experienced programmers who think about this the wrong way.) To execute print(numberOfKazoos = 94); Dart covertly substitutes 94 for the expression numberOfKazoos = 94, as shown in Figure 4-7.

Snapshot of Dart's innermost thoughts.

FIGURE 4-7: Dart’s innermost thoughts.

In other words, the value numberOfKazoos = 94 is 94. So, in addition to doing something, the code numberOfKazoos = 94 also has a value. That’s why numberOfKazoos = 94 is both a statement and an expression.

Simple assignment statements aren’t the only things that double as expressions. Try this code out for size:

numberOfKazoos = 100;
print(numberOfKazoos);
print(numberOfKazoos++);
print(numberOfKazoos);

The code’s output is

flutter: 100
flutter: 100
flutter: 101

If the middle line of output surprises you, you’re not alone. As a statement, numberOfKazoos++ adds 1 to the value of numberOfKazoos, changing the value from 100 to 101. But, as an expression, the value of numberOfKazoos++ is 100, not 101. (Refer to Figure 4-7.)

Here’s a comforting thought. By the time Dart executes the last print(numberOfKazoos) statement, the value of numberOfKazoos has already changed to 101. Whew!

Tip As a statement, ++numberOfKazoos (with the plus signs in front) does the same thing that numberOfKazoos++ does: It adds 1 to the value of numberOfKazoos. But, as an expression, the value of ++numberOfKazoos isn’t the same as the value of numberOfKazoos++. Try it. You’ll see.

Dart has some other statements whose values are expressions. For example, the following code prints flutter: 15 twice:

int howManyGiraffes = 10;
print(howManyGiraffes += 5);
print(howManyGiraffes);

And the following code prints flutter: 5000 twice:

int rabbitCount = 500;
print(rabbitCount *= 10);
print(rabbitCount);

On the web For more info about topics like += and *=, visit this page:

https://dart.dev/guides/language/language-tour#operators

Dart’s var keyword

On occasion, you might want to create a variable whose type can change. To do so, declare the variable using Dart’s var keyword and leave out an initialization in the declaration. For example, the following code won’t work:

int x = 7;
print(x);
x = "Someone's trying to turn me into a String"; // You can’t do this
print(x);

But the following code works just fine:

var x;
x = 7;
print(x);
x = "I've been turned into a String"; // Dart is happy to oblige
print(x);

Another reason for using var is to avoid long, complicated type names. For an example, see this chapter’s “Build-in types” section.

Built-in types

In a Dart program, every value has a type. Dart has ten built-in types. (See Table 4-2.)

TABLE 4-2 Dart’s Built-In Types

Type Name

What Literals Look Like

Useful Info About the Type

Number types

int

42

Numbers with no digits to the right of the decimal point — typically, from –9007199254740992 to 9007199254740991.

double

42.0 42.1

Numbers with digits to the right of the decimal point (possibly, all zero digits).

num

42 42.0 42.1

A number of some kind. Every int value, and every double value, is an example of a num value.

Collection types

List

[2, 4, –9, 25, 18]

["Hello", "Goodbye", 86]

[]

<int>[]

A bunch of values. The initial value is the 0th, the next value is the 1st, the next value is the 2nd, and so on. (With [], the bunch has no values in it.)

Set

{2, 4, –9, 25, 18}

{"Hello", "Goodbye", 86}

{}

<int>{}

A bunch of values with no duplicates in no particular order. (With {}, the bunch has no values in it.)

Map

{ ’one’ : 1, ’two’ : 2 ,

’three’ : 3, ’many’: 99}

<String, int>{}

A bunch of pairs, each pair consisting of a key (such as ’one’, ’two’, ’three’, or ’many’) and a value (such as 1, 2, 3, or 99). (With {}, the bunch has no pairs in it.)

Other types

String

’Dart is boring’

""

"""The previous

string is empty."""

A sequence of characters.

bool

true, false

A logical value. A variable of this type has one of only two possible values: true and false.

Runes

Runes(’I ’ ’u2665’ ’ you’)

A string of Unicode characters. For example, ’u2665’ is a heart character (♥).

Symbol

(Not applicable)

Turns an identifier in a Dart program into a value in a Dart program. (Don’t worry about it!)

You can combine types to create new types. One way to do this is to put types inside of collection types. For example, in the following declaration, the variable amounts is a List containing only int values.

List<int> amounts = [7, 3, 8, 2];

Of course, you can go crazy layering types within types within other types:

Map<String, Map<String, List<int>>> values = {
"Size": {
"Small": [1, 2, 3],
},
};

In cases like that, your best bet is to use the var keyword. Dart can usually figure things out by looking at the rest of the code.

var values = {
"Size": {
"Small": [1, 2, 3],
},
};

Types that aren’t built-in

In addition to the types in Table 4-2, every class is a type. For example, in Listing 4-1, App0401 is the name of a type. It’s a type that’s defined in Listing 4-1. You can add a line to Listing 4-1 that makes a variable refer to an instance of the App0401 class. Here’s one such line:

App0401 myApp = App0401();

Like many other variable declarations, this line has a type name (App0401), followed by a new variable name (myApp), followed by an initialization. The initialization makes myApp refer to a newly constructed App0401 instance.

The Dart language comes with a library full of standard, reusable code. The formal name for such a library is an application programming interface (API). Dart’s API has declarations of many classes. For example, instances of Dart’s DateTime class are moments in time, and instances of the Duration class are time intervals.

Similarly, the Flutter toolkit comes with a feature-rich API. In Listing 4-1, Widget, StatelessWidget, BuildContext, MaterialApp, Material, Center, and Text are the names of classes in the Flutter API.

Using import declarations

Woe is me! I can’t read the book Flutter For Dummies unless I go to my local library and check out a copy. The same is true of Dart’s and Flutter’s library classes (well, almost). You can’t use Flutter’s MaterialApp or Material classes unless you start your program with

import 'package:flutter/material.dart';

If you delete this line, you can’t even use any of Flutter’s Widget classes (StatelessWidget, Widget, Center, and Text, to name a few). That’s because, when you import ’package:flutter/material.dart’, you automatically import ’package:flutter/widgets.dart’ also.

A relatively small number of Dart’s API classes, like the aforementioned DateTime class, belong to a package named dart.core. You can start your program with the line

import 'dart:core';

but it won’t do you any good. Classes from the dart.core package are always imported, whether you ask for it or not.

Remember No one (and I do mean no one) memorizes the names of all the classes in the Dart or Flutter libraries. When you need to know about a class, look it up by visiting https://api.flutter.dev.

Variations on a Theme from Die Flutter Mouse

This section shows some alternative ways of creating function declarations. Listing 4-3 has the first example.

LISTING 4-3 Messing with Function Declarations

import 'package:flutter/material.dart';
 
main() {
runApp(App0403());
}
 
class App0403 extends StatelessWidget {
Widget build(BuildContext context) {
return MaterialApp(
home: Material(
child: Center(child: Text(highlight("Look at me"))),
),
);
}
}
 
highlight(words) => "*** $words ***";

Crossreference To read all about the dollar sign ($) on the last line of Listing 4-3, see the nearby “Bling your string” sidebar.

A run of the code in Listing 4-3 is the same as that of Listing 4-2. (Refer to Figure 4-1.) In a sense, Listing 4-3 contains the same program as Listing 4-2. The notation for things is slightly different, but the things themselves are the same.

In Listing 4-3, the highlight function declaration

highlight(words) => "*** $words ***";

is shorthand for the more long-winded highlight declaration in Listing 4-2. When the body of a function declaration contains only one statement, you can use this quick-and-easy fat arrow (=>) notation.

Remember In a fat arrow function declaration, you never use the return keyword.

Back in Listing 4-2, I use the fat arrow notation to declare the main function. Just to show that I can do it, I “un-fat-arrow” this declaration in Listing 4-3.

Every Dart program has a function named main. When you start running a program, Dart looks for the program’s main function declaration and starts executing whatever statements are in the declaration’s body. In a Flutter app, a statement like

runApp(App0403());

tells Dart to construct an instance of App0403 and then run that instance. The runApp function is part of Flutter’s API.

Type names in function declarations

Listing 4-4 adds some type names to the code from Listing 4-2.

LISTING 4-4 Better Safe than Sorry

import 'package:flutter/material.dart';
 
void main() => runApp(App0404());
 
class App0404 extends StatelessWidget {
Widget build(BuildContext context) {
return MaterialApp(
home: Material(
child: Center(child: Text(highlight("Look at me"))),
),
);
}
}
 
String highlight(String words) {
return "*** $words ***";
}

In Listing 4-4, String and void add some welcome redundancy to the code. The occurrence of String in (String words) tells Dart that, in any call to the highlight function, the words parameter must have type String. Armed with this extra String information, Dart will cough up and spit out a bad function call such as

highlight(19)

This is bad because 19 is a number, not a String. You may argue and say, “I’ll never make the mistake of putting a number in a call to the highlight function.” And my response is, “Yes you will, and so will I, and so will every other programmer on earth.” When you’re writing code, mistakes are inevitable. The trick is to catch them sooner rather than later.

Near the end of Listing 4-4, String highlight tells Dart that the value returned by the highlight function must be a String. If you accidentally write the following code, Dart will complain like nobody’s business:

String highlight(String words) {
return 99; //Bad code!
}

Sorry, chief. The value 99 isn’t a String.

Continuing our journey through Listing 4-4, void main doesn’t quite mean, “The main function must return a value of type void.” Why not? It’s okay to put a type name in front of a fat arrow declaration. So, what’s different about void main?

Simply stated, void isn’t a type. In a way, void means “no type.” The word void reminds Dart that this main function isn’t supposed to return anything useful. Try declaring void main and putting a return statement in the declaration’s body:

void main() {
runApp(App0404());
return 0; // Bad
}

If you do this, Android Studio’s editor adds red marks to your code. Dart is saying, “Sorry, Bud. You can’t do that.”

Naming your parameters

Chapter 3 distinguishes between constructors’ positional parameters and named parameters. All that fuss about the kinds of parameters applies to functions as well. For example, the highlight function in Listing 4-4 has one parameter — a positional parameter.

highlight("Look at me") // A function call
 
String highlight(String words) { // The function declaration
return "*** $words ***";
}

If you want, you can turn words into a named parameter. Simply surround the parameter with curly braces:

highlight(words: "Look at me") // A function call
 
String highlight({String words}) { // The function declaration
return "*** " + words + " ***";
}

You can even have a function with both positional and named parameters. In the parameter list, all the positional parameters must come before any of the named parameters. For example, the following code displays +++Look at me!+++.

highlight( // A function call
"Look at me",
punctuation: "!",
symbols: "+++",
)
 
String highlight( // The function declaration
String words, {
String punctuation,
String symbols,
}) {
return symbols + words + punctuation + symbols;
}

What about the build function?

Listing 4-4 contains some familiar-looking code:

class App0404 extends StatelessWidget {
Widget build(BuildContext context) {
return MaterialApp(

Here are some facts:

  • In this code, build is the name of a function, and

    Widget build(BuildContext context)

    is the function declaration’s header.

    The build function does exactly what its name suggests. It builds something. To be precise, it builds the widget whose content is the entire Flutter app.

  • The build function returns a value of type Widget.

    Quoting from Chapter 3, “Being an instance of one class might make you automatically be an instance of a bigger class.” In fact, every instance of the MaterialApp class is automatically an instance of the StatefulWidget class, which, in turn, is automatically an instance of the Widget class. So there you have it — every MaterialApp is a Widget. That’s why it’s okay for the build function’s return statement to return a MaterialApp object.

  • The function’s one-and-only parameter has the type BuildContext.

    When Dart builds a widget, Dart creates a BuildContext object and passes that to the widget’s build function. A BuildContext object contains information about the widget and the widget’s relationship to other widgets in the program. For more info, see Chapter 6.

In Listing 4-4, the build function’s declaration is inside the class App0404 definition, but the highlight function declaration isn’t inside any class definition. In a sense, this build function “belongs to” instances of the App0404 class.

A function that belongs to a class, or to the class’s instances, has a special name. It’s called a method. More on this in Chapter 5.

More Fun to Come!

What happens if a user taps the screen and wants a response from the app in Listing 4-4? Absolutely nothing.

Let’s fix that. Turn the page to see what’s in Chapter 5.

♪ “Goodbye from us to you.” ♪

— BUFFALO BOB ON “THE HOWDY DOODY SHOW,” 1947–1960

..................Content has been hidden....................

You can't read the all page of ebook, please click here login for view all page.
Reset
18.188.66.13