Chapters

Hide chapters

Dart Apprentice: Fundamentals

First Edition · Flutter · Dart 2.18 · VS Code 1.71

Dart Apprentice: Fundamentals

Section 1: 16 chapters
Show chapters Hide chapters

10. Static Members
Written by Jonathan Sande

Heads up... You're reading this book for free, with parts of this chapter shown beyond this point as scrambled text.

There’s just one more thing to cover for your well-rounded foundation in Dart classes. That’s the static keyword. No relationship to static electricity.

Putting static in front of a member variable or method causes the variable or method to belong to the class rather than the instance.

class SomeClass {
  static int myProperty = 0;
  static void myMethod() {
    print('Hello, Dart!');
  }
}

They work the same as top-level variables and functions but are wrapped in the class name.

You access them like so:

final value = SomeClass.myProperty;
SomeClass.myMethod();

In this case, you didn’t have to instantiate an object to access myProperty or to call myMethod. Instead, you used the class name directly to get the value and call the method.

The following sections will cover a few common use cases for static members.

Static Variables

Static variables are often used for constants and in the singleton pattern.

Note: Variables receive different names according to where they belong or are located. Because static variables belong to the class, they’re called class variables. Non-static member variables are called instance variables because they only have a value after an object is instantiated. Variables within a method are called local variables. And top-level variables outside of a class are called global variables.

Constants

Many classes store useful values that never change. Some examples of these class constants include the following:

Default Font Size Example

You can define class constants by combining the static and const keywords. For example, add the following class to your project below main:

class TextStyle {
  static const _defaultFontSize = 17.0;

  TextStyle({this.fontSize = _defaultFontSize});
  final double fontSize;
}

Color Codes Example

In the previous example, the constant was private, but it can also be useful to have public constants. You’ll see this with Flutter’s Colors class. You’ll make a simplified version here.

class Colors {
  static const int red = 0xFFD13F13;
  static const int purple = 0xFF8107D9;
  static const int blue = 0xFF1432C9;
}
final backgroundColor = Colors.purple;

Singleton Pattern

Another use of static variables is to create a singleton class. Singletons are a common design pattern with only one instance of an object. Although some people debate their benefits, they make certain tasks more convenient.

class MySingleton {
  MySingleton._();
  static final MySingleton instance = MySingleton._();
}
final mySingleton = MySingleton.instance;
class MySingleton {
  MySingleton._();
  static final MySingleton _instance = MySingleton._();
  factory MySingleton() => _instance;
}
final mySingleton = MySingleton();

Static Methods

You can do a few interesting things with static methods.

Utility Methods

One use for a static method is to create a utility or helper method associated with the class but not with any particular instance.

class Math {
  static num max(num a, num b) {
    return (a > b) ? a : b;
  }

  static num min(num a, num b) {
    return (a < b) ? a : b;
  }
}
print(Math.max(2, 3));  // 3
print(Math.min(2, 3));  // 2

Just Because You Can, Doesn’t Mean You Should

In other languages, some developers like to group related static utility methods in classes to keep them organized. But in Dart, it’s usually better to put these utility methods in their own file as top-level functions. You can then import that file as a library wherever you need the utility methods contained within. The description below will show you how to refactor your Math class into a library of top-level functions.

num max(num a, num b) {
  return (a > b) ? a : b;
}

num min(num a, num b) {
  return (a < b) ? a : b;
}
import 'package:starter/math.dart';
print(max(2, 3)); // 3
print(min(2, 3)); // 2
import 'package:starter/math.dart' as math;

void main() {
  print(math.max(2, 3)); // 3
  print(math.min(2, 3)); // 2
}

Creating New Objects

You can also use static methods to create new instances of a class based on some input passed in. For example, you could use a static method to achieve the same result as in the previous chapter with the fromJson factory constructor.

factory User.fromJson(Map<String, Object> json) {
  final userId = json['id'] as int;
  final userName = json['name'] as String;
  return User(id: userId, name: userName);
}
static User fromJson(Map<String, Object> json) {
  final userId = json['id'] as int;
  final userName = json['name'] as String;
  return User(id: userId, name: userName);
}
final map = {'id': 10, 'name': 'Sandra'};
final sandra = User.fromJson(map);

Comparing Static Methods With Factory Constructors

Factory constructors are like static methods in many ways, but there are a few differences:

Challenges

Before moving on, here’s a challenge to test your knowledge of static members. It’s best if you try to solve it yourself, but a solution is available with the supplementary materials for this book if you get stuck.

Challenge 1: Spheres

Create a Sphere class with a const constructor that takes a radius as a named parameter. Add getters for the volume and surface area but none for the radius. Don’t use the dart:math package but store your version of pi as a static constant. Use your class to find the volume and surface area of a sphere with a radius of 12.

Key Points

  • Adding the static keyword to a property or method makes it belong to the class rather than the instance.
  • Static constants are useful for storing values that don’t change.
  • A singleton is a class with only one instance of an object.
  • A utility method is a method that’s associated with the class but not with any particular instance.
  • Group top-level functions into their own library rather than wrapping a bunch of static methods in a utility class.
  • Static methods can replace factory constructors but have a few subtle differences from factory constructors.

Where to Go From Here?

This chapter touched on concepts such as singletons and factories. These concepts are known collectively as design patterns. Although you don’t need to know design patterns to code in Dart, understanding them will make you a better programmer. The most famous book on this topic is Design Patterns by “The Gang of Four”, but there are many other excellent works on the subject. A simple online search for software design patterns will provide you a wealth of information.

Have a technical question? Want to report a bug? You can ask questions and report bugs to the book authors in our official book forum here.
© 2024 Kodeco Inc.

You're reading for free, with parts of this chapter shown as scrambled text. Unlock this book, and our entire catalogue of books and videos, with a Kodeco Personal Plan.

Unlock now