Flutter Widgets Deep Dive Part 1: Square Peg in a Round Hole — Generics in Dart

Ahmed Abu_eldahab
Flutter Community
Published in
5 min readNov 13, 2018

--

Hello Flutterisans :), after giving more than 40 talks about Flutter within the past year, all of which were in different countries, I found there are some repeated questions beginners keep asking me. There are also some ambiguous points about Flutter new developers misunderstand.

In this series of articles I’ll try to explain some important concepts about Flutter and Dart that are important for anyone at the beginning of his or her Flutter journey. I’ll also try to explain the general theory of how things work inside of Flutter & Dart.

These articles will cover the following points:

  • Generics in Dart: Both the Problem and the Solution.
  • Why there are two types of widgets inside flutter(Stateless & Stateful) and when each should be used.
  • Life without StatefulWidget
  • Why the StatefulWidget and it’s State are separate classes.
  • Widgets and the Render Tree
  • Flutter widgets you should know.
  • Testing in Flutter (Unit testing — Widget testing — Integration testing)

Square Peg in a Round Hole

Square Peg in a Round Hole

Let’s simulate a classic game, putting a square peg into a round hole. You might say we can’t put a square peg into a round hole, and that’s a problem. So how can we solve this problem using Dart?

Let’s create three classes:

  • One class to represent the Slot.
  • Another class to represent the square peg.
  • The third class to represent the circle peg.

The Slot class has a method called “insert”. This method will be used to insert the shape.

So what is the problem?

The problem is when the Slot class is instantiated, I need to know if this particular slot is made for a circle or for a square.

You might be wondering why we don’t just create two types of slots, one for a Circle and another for a Square:

But when we try to insert a shape that’s not compatible with the slot type we’re trying to use, the compiler complains:

Dart compiler error. A Circle can’t be assigned to a Square
Here we see you not only can’t put a square peg into a round hole, you can’t put a round peg into a square hole either!

At this point, you might be wondering:

  1. Is this really the best approach for solving this problem?

2. Might there be a better way to solve the problem without writing custom code for every different Slot type?

3. Is there a solution that would still work if we added more types besides Circle and Square?

The answer is Yes, Yes and Yes! You can do all of this using Generics.

Generics allow us to write code we’ll be able to reuse easily; without needing to write custom code for each different type of shape.

Let’s refactor our code again but this time we’ll use Generics:

From the snippet above, you can see we used letter T inside a pair of <> brackets to denote a generic type. We can specify the Slot type when creating the instance of our shape as shown in line 2.

This code is more elegant, easier to work with plus it’s now reusable; and if we try to insert a shape type that doesn’t match our Slot type, the code still won’t let that happen:

This approach makes our code better and more reusable.

Why am I explaining all of this? Why do I need to understand this when starting with Flutter?

The answer to this lies in the standard code that is generated when you create a new Flutter app. In main.dart, you’ll find two classes: MyHomePage and _MyHomePageState. MyHomePage extends StatefulWidget (Line #1) and _MyHomePageState extends State class (Line #7 ). This is shown in the code snippet below:

Something commonly misunderstood by people new to Flutter, or to statically typed languages in general, is the following line:

As you can see, we want to create a _MyHomePageState class that extends State. If you look carefully, you’ll see that the State class has a generic type <T>, and so we’re going to want to specify what Type we’re going to be using in place of T for our new _MyHomePageState class. When creating a State we need to define what it is the State of. We do this by defining T, which in this case is going to be our StatefulWidget, MyHomePage.

If you were to check the source code, this is what you’d find:

Class declaration for "State"

Since the source code needs to be reusable anytime we need to create a State for a StatefulWidget, it uses a generic type <T>.

Simply put, we’re telling Flutter to create a class _MyHomePageState which will borrow some functionality from State. Since we need to make sure this Stateis only responsible for a single StatefulWidget, we type it by adding that Widget’s type in <> brackets (here we use MyHomePage) . By doing so, we tie this instance ofState to the MyHomePage class.

This process is exactly what we did to our Slot class earlier.

So when you see State<MyHomePage> remember Slot<Circle>. This is how Flutter’s Stateclass uses generics from Dart. It ensures that when you create a State, it’s only referenced by one the StatefulWidget it belongs to.

Generics having been addressed, we can focus on what StatefulWidget & StatelessWidget mean and when, or why, we should be using each. This will be discussed in our next article :)

See you soon and best regards,

Ahmed

--

--

Ahmed Abu_eldahab
Flutter Community

Google Developer Expert in Flutter & Dart ,An Entrepreneur, Public Speaker , @FlutterEgypt Founder & Community Organizer , @GDGAlexandria @dahabdev