List의 기본 배열 유형에 대한 API 문서를 보면 형식이 실제로 List<E>이다. <...>표기법은 List를 제네릭(또는 매개변수화) 타입으로 표시한다. 타입은 타입 매개 변수가 있는 타입이다. By Convention 대부분의 타입 변수는 E, T, S, K 및 V와 같은 한 문자로 된 이름을 가지고 있다.
왜 제네릭을 사용해야 할까요? (Why use generics?)
제네릭은 타입 안전성을 위해 종종 필요하지만 코드 실행을 허용하는 것보다 많은 장점이 있다.
제네릭 형식을 올바르게 지정하면 코드를 더 잘 생성 할 수 있다.
제네릭을 사용하여 코드 중복을 줄일 수 있다.
리스트에만 문자열을 포함 시키려면 List<String>( "string of list"로 읽음)으로 선언 할 수 있다. 그렇게 하면 여러분, 동료 프로그래머, 그리고 여러분의 도구가 비문자열(non-string)을 리스트에 대입하는 것이 실수 일 수 있음을 감지 할 수 있다. 다음은 그 예이다.
var names =List<String>();names.addAll(['Seth','Kathy','Lars']);names.add(42);// Error
제네릭을 사용하는 또 다른 이유는 코드 중복을 줄이는 것이다. 제네릭을 사용하면 정적 분석을 활용하면서 여러 타입간에 단일 인터페이스와 구현을 공유 할 수 있다. 예를 들어, 객체 캐싱을위한 인터페이스를 생성한다고 가정 해보십시오.
abstract class Cache<T> {
T getByKey(String key);
void setByKey(String key, T value);
}
var names = <String>['Seth', 'Kathy', 'Lars'];
var uniqueNames = <String>{'Seth', 'Kathy', 'Lars'};
var pages = <String, String>{
'index.html': 'Homepage',
'robots.txt': 'Hints for web robots',
'humans.txt': 'We are people, not machines'
};
var nameSet = Set<String>.from(names);
var views = Map<int, View>();
var names = List<String>();
names.addAll(['Seth', 'Kathy', 'Lars']);
print(names is List<String>); // true
class Foo<T extends SomeBaseClass> {
// Implementation goes here...
String toString() => "Instance of 'Foo<$T>'";
}
class Extender extends SomeBaseClass {...}
var someBaseClassFoo = Foo<SomeBaseClass>();
var extenderFoo = Foo<Extender>();
var foo = Foo();
print(foo); // 'Foo<SomeBaseClass>'의 인스턴스
var foo = Foo<Object>();
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;
}