Google uses cookies to deliver its services, to personalize ads, and to
analyze traffic. You can adjust your privacy controls anytime in your
Google settings <[Link]
Learn more <[Link]
Okay
/menu/
Dart <[Link]
* Overview <[Link]
* Docs <[Link]
* Community <[Link]
* Try Dart <[Link]
* Get Dart <[Link]
*
Dart 3.1 is out, with updates supporting the new features from Dart 3.0.
Check out the blog post <[Link]
* Overview <[Link]
* Community <[Link]
* Try Dart <[Link]
* Get Dart <[Link]
* Docs <[Link]
* Tutorials & codelabs <#sidenav-1>
o Tutorials <[Link]
o Codelabs <#sidenav-1-2>
+ List of Dart codelabs <[Link]
+ Language cheatsheet <[Link]
+ Iterable collections <[Link]
+ Asynchronous programming
<[Link]
+ Null safety <[Link]
* Language <#sidenav-2>
o Introduction <[Link]
o Syntax basics <#sidenav-2-2>
+ Variables <[Link]
+ Operators <[Link]
+ Comments <[Link]
+ Metadata <[Link]
+ Libraries & imports <[Link]
+ Keywords <[Link]
o Types <#sidenav-2-3>
+ Built-in types <[Link]
+ Records <[Link]
+ Collections <[Link]
+ Generics <[Link]
+ Typedefs <[Link]
+ Type system <[Link]
o Patterns <#sidenav-2-4>
+ Overview & usage <[Link]
+ Pattern types <[Link]
o Functions <[Link]
o Control flow <#sidenav-2-6>
+ Loops <[Link]
+ Branches <[Link]
o Error handling <[Link]
o Classes & objects <#sidenav-2-8>
+ Classes <[Link]
+ Constructors <[Link]
+ Methods <[Link]
+ Extend a class <[Link]
+ Mixins <[Link]
+ Enums <[Link]
+ Extension methods <[Link]
+ Callable objects <[Link]
o Class modifiers <#sidenav-2-9>
+ Overview & usage <[Link]
+ Class modifiers for API maintainers
<[Link]
+ Reference <[Link]
o Concurrency <#sidenav-2-10>
+ Asynchronous support <[Link]
+ Isolates <[Link]
o Null safety <#sidenav-2-11>
+ Sound null safety <[Link]
+ Migrating to null safety
<[Link]
+ Understanding null safety
<[Link]
+ Unsound null safety
<[Link]
+ FAQ <[Link]
* Effective Dart <#sidenav-3>
o Overview <[Link]
o Style <[Link]
o Documentation <[Link]
o Usage <[Link]
o Design <[Link]
* Core libraries <#sidenav-4>
o Overview <[Link]
o Tour <[Link]
o Articles <#sidenav-4-3>
+ Creating streams
<[Link]
* Packages <#sidenav-5>
o How to use packages <[Link]
o Commonly used packages
<[Link]
o Creating packages
<[Link]
o Publishing packages <[Link]
o Writing package pages
<[Link]
o Package reference <#sidenav-5-6>
+ Dependencies <[Link]
+ Glossary <[Link]
+ Package layout conventions
<[Link]
+ Pub environment variables
<[Link]
+ Pubspec file <[Link]
+ Troubleshooting pub <[Link]
+ Verified publishers
<[Link]
+ Versioning <[Link]
* Development <#sidenav-6>
o Futures, async, await <[Link]
o Streams <[Link]
o JSON <[Link]
o Number representation <[Link]
o Interoperability <#sidenav-6-5>
+ C interop <[Link]
+ Objective-C & Swift interop
<[Link]
+ Java & Kotlin interop
<[Link]
+ JavaScript interop <[Link]
o Google APIs <[Link]
o Multi-platform apps <[Link]
o Command-line & server apps <#sidenav-6-8>
+ Overview <[Link]
+ Get started <[Link]
+ Write command-line apps
<[Link]
+ Fetch data from the internet
<[Link]
+ Write HTTP servers
<[Link]
+ Libraries & packages <[Link]
+ Google Cloud <[Link]
o Web apps <#sidenav-6-9>
+ Overview <[Link]
+ Get started <[Link]
+ Low-level web programming <#sidenav-6-9-3>
# Connect Dart & HTML
<[Link]
# Add elements to the DOM
<[Link]
# Remove DOM elements
<[Link]
+ Deployment <[Link]
+ Libraries & packages <[Link]
o Environment declarations
<[Link]
* Tools & techniques <#sidenav-7>
o Overview <[Link]
o Editors & debuggers <#sidenav-7-2>
+ IntelliJ & Android Studio
<[Link]
+ VS Code <[Link]
+ Dart DevTools <[Link]
+ DartPad <#sidenav-7-2-4>
# Overview <[Link]
# DartPad in tutorials
<[Link]
# Troubleshooting DartPad
<[Link]
o Command-line tools <#sidenav-7-3>
+ Dart SDK <#sidenav-7-3-1>
# Overview <[Link]
# dart <[Link]
# dart analyze <[Link]
# dart compile <[Link]
# dart create <[Link]
# dart doc <[Link]
# dart fix <[Link]
# dart format <[Link]
# dart info <[Link]
# dart pub <[Link]
# dart run <[Link]
# dart test <[Link]
# dartaotruntime <[Link]
# Experiment flags <[Link]
+ Other command-line tools <#sidenav-7-3-2>
# build_runner <[Link]
# webdev <[Link]
o Managing source code <#sidenav-7-4>
+ Formatting code <[Link]
+ What not to commit
<[Link]
o Static analysis <#sidenav-7-5>
+ Customizing static analysis <[Link]
+ Fixing common type problems
<[Link]
+ Diagnostic messages
<[Link]
+ Linter rules <[Link]
o Testing & optimization <#sidenav-7-6>
+ Testing <[Link]
+ Debugging web apps <[Link]
* Resources <#sidenav-8>
o FAQ <[Link]
o Breaking changes <[Link]
o Language evolution <[Link]
o Language specification <[Link]
o Dart 3 migration guide
<[Link]
o Coming from ... <#sidenav-8-6>
+ JavaScript to Dart
<[Link]
+ Swift to Dart
<[Link]
o Glossary <[Link]
o Books <[Link]
o Videos <[Link]
* Related sites <#sidenav-9>
o API referenceopen_in_new <[Link]
o Blogopen_in_new <[Link]
o DartPad (online editor)open_in_new <[Link]
o Flutteropen_in_new <[Link]
o Package siteopen_in_new <[Link]
Contents
* Why use generics? <#why-use-generics>
* Using collection literals <#using-collection-literals>
* Using parameterized types with constructors
<#using-parameterized-types-with-constructors>
* Generic collections and the types they contain
<#generic-collections-and-the-types-they-contain>
* Restricting the parameterized type <#restricting-the-parameterized-type>
* Using generic methods <#using-generic-methods>
* ⟨ Collections <[Link]
* Typedefs ⟩ <[Link]
/description/
<[Link]
/bug_report/ <[Link]
template=1_page_issue.yml&title=[PAGE%20ISSUE]:%20%27Generics%27&page-url=https://
[Link]/language/[Link]&page-source=[Link]
tree/main/src/language/[Link]>
Generics
Contents
* Why use generics? <#why-use-generics>
* Using collection literals <#using-collection-literals>
* Using parameterized types with constructors
<#using-parameterized-types-with-constructors>
* Generic collections and the types they contain
<#generic-collections-and-the-types-they-contain>
* Restricting the parameterized type <#restricting-the-parameterized-type>
* Using generic methods <#using-generic-methods>
If you look at the API documentation for the basic array type, |List|
<[Link] you’ll see that
the type is actually |List<E>|. The <…> notation marks List as a
/generic/ (or /parameterized/) type—a type that has formal type
parameters. By convention
<[Link]
when-naming-type-parameters>, most type variables have single-letter names, such as
E, T, S, K, and V.
<#why-use-generics>Why use generics?
Generics are often required for type safety, but they have more benefits
than just allowing your code to run:
* Properly specifying generic types results in better generated code.
* You can use generics to reduce code duplication.
If you intend for a list to contain only strings, you can declare it as
|List<String>| (read that as “list of string”). That way you, your
fellow programmers, and your tools can detect that assigning a
non-string to the list is probably a mistake. Here’s an example:
|var names = <String>[];
[Link](['Seth', 'Kathy', 'Lars']);
[Link](42); // Error
|
Another reason for using generics is to reduce code duplication.
Generics let you share a single interface and implementation between
many types, while still taking advantage of static analysis. For
example, say you create an interface for caching an object:
|abstract class ObjectCache {
Object getByKey(String key);
void setByKey(String key, Object value);
}|
You discover that you want a string-specific version of this interface,
so you create another interface:
|abstract class StringCache {
String getByKey(String key);
void setByKey(String key, String value);
}|
Later, you decide you want a number-specific version of this interface…
You get the idea.
Generic types can save you the trouble of creating all these interfaces.
Instead, you can create a single interface that takes a type parameter:
|abstract class Cache<T> {
T getByKey(String key);
void setByKey(String key, T value);
}|
In this code, T is the stand-in type. It’s a placeholder that you can
think of as a type that a developer will define later.
<#using-collection-literals>Using collection literals
List, set, and map literals can be parameterized. Parameterized literals
are just like the literals you’ve already seen, except that you add
|</type/>| (for lists and sets) or |</keyType/, /valueType/>| (for maps)
before the opening bracket. Here is an example of using typed literals:
|var names = <String>['Seth', 'Kathy', 'Lars'];
var uniqueNames = <String>{'Seth', 'Kathy', 'Lars'};
var pages = <String, String>{
'[Link]': 'Homepage',
'[Link]': 'Hints for web robots',
'[Link]': 'We are people, not machines'
};|
<#using-parameterized-types-with-constructors>Using parameterized
types with constructors
To specify one or more types when using a constructor, put the types in
angle brackets (|<...>|) just after the class name. For example:
|var nameSet = Set<String>.from(names);|
The following code creates a map that has integer keys and values of
type View:
|var views = Map<int, View>();|
<#generic-collections-and-the-types-they-contain>Generic collections
and the types they contain
Dart generic types are /reified/, which means that they carry their type
information around at runtime. For example, you can test the type of a
collection:
|var names = <String>[];
[Link](['Seth', 'Kathy', 'Lars']);
print(names is List<String>); // true|
/info/ *Note:* In contrast, generics in Java use /erasure/, which means
that generic type parameters are removed at runtime. In Java, you can
test whether an object is a List, but you can’t test whether it’s a
|List<String>|.
<#restricting-the-parameterized-type>Restricting the parameterized type
When implementing a generic type, you might want to limit the types that
can be provided as arguments, so that the argument must be a subtype of
a particular type. You can do this using |extends|.
A common use case is ensuring that a type is non-nullable by making it a
subtype of |Object| (instead of the default, |Object?|
<[Link]
|class Foo<T extends Object> {
// Any type provided to Foo for T must be non-nullable.
}|
You can use |extends| with other types besides |Object|. Here’s an
example of extending |SomeBaseClass|, so that members of |SomeBaseClass|
can be called on objects of type |T|:
|class Foo<T extends SomeBaseClass> {
// Implementation goes here...
String toString() => "Instance of 'Foo<$T>'";
}
class Extender extends SomeBaseClass {...}|
It’s OK to use |SomeBaseClass| or any of its subtypes as the generic
argument:
|var someBaseClassFoo = Foo<SomeBaseClass>();
var extenderFoo = Foo<Extender>();|
It’s also OK to specify no generic argument:
|var foo = Foo();
print(foo); // Instance of 'Foo<SomeBaseClass>'|
Specifying any non-|SomeBaseClass| type results in an error:
|var foo = Foo<Object>();|
<#using-generic-methods>Using generic methods
Methods and functions also allow type arguments:
|T first<T>(List<T> ts) {
// Do some initial work or error checking, then...
T tmp = ts[0];
// Do some additional checking or processing...
return tmp;
}|
Here the generic type parameter on |first| (|<T>|) allows you to use the
type argument |T| in several places:
* In the function’s return type (|T|).
* In the type of an argument (|List<T>|).
* In the type of a local variable (|T tmp|).
* ⟨ Collections <[Link]
* Typedefs ⟩ <[Link]
Dart <[Link]
<[Link] <[Link]
<[Link]
Except as otherwise noted, this site is licensed under a Creative
Commons Attribution 4.0 International License
<[Link] and code samples are
licensed under the 3-Clause BSD License
<[Link]
* Terms <[Link]
* Privacy <[Link]
* Security <[Link]