본문 바로가기
기타개발/Flutter

Dart #8 : Generics

by 궝테스트 2020. 8. 28.

Dart : https://dart.dev/guides/language/language-tour

  • 기본 배열 타입인 List API 문서를 보면 타입이 실제로 List<E> 인 것을 볼 수 있다
  • 이러한 <…> 표기법은 List 를 generic (또는 매개 변수화 된) 타입으로 표시한다. (정식 유형 매개 변수가있는 타입)
  • 대부분의 타입 변수에는 E, T, S, K, V 와 같은 단일 문자들이 있다

 

0. Why use generics?

  • 제네릭은 type-safety 를 위해 필요하기도 하고 그 외 더 많은 이점이 있다
    • generic type 을 올바르게 지정하면 코드가 더 잘 생성된다
    • generic 을 사용하여 코드 중복을 줄일 수 있다
  • 만약 List  에 String 만 포함되도록 하려면 List<String> 으로 선언 할 수 있다
    이렇게하면 동료 프로그래머와 tool 이 List 에 String 이 아닌 것을 할당하려 할 때 감지할 수 있다
var names = List<String>();
names.addAll(['Seth', 'Kathy', 'Lars']);
names.add(42); // Error
  • 제네릭 코드 중복을 줄여준다
  • 제네릭을 사용하면 여러 타입간에 단일 인터페이스와 구현을 공유하면서 정적 분석을 계속 활용할 수 있다
  • 예를 들어, 아래와 같이 객체 캐싱을 위한 인터페이스를 생성한다고 가정한다
  • ObjectCache 인터페이스의 String 으로 된 버전이 필요하니 StringCache 처럼 인터페이스를 만들 수 있다
abstract class ObjectCache {
  Object getByKey(String key);
  void setByKey(String key, Object value);
}

abstract class StringCache {
  String getByKey(String key);
  void setByKey(String key, String value);
}
  • 만약에 int 로 된 value 를 받아야 할 수도 있다. 그럴 땐 아래처럼 제네릭 타입을 사용할 수 있다
abstract class Cache<T> {
  T getByKey(String key);
  void setByKey(String key, T value);
}

 

1. Using collection literals

  • List, Set, Map 리터럴을 매개 변수화 할 수 있다
  • List 와 Set 의 경우 <type> 만 추가한다
  • Map 의 경우 <keyType, valueType> 추가한다
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'
};

 

2. Using parameterized types with constructors

  • 생성자를 사용할 때 하나 이상의 타입을 지정하려면 클래스 이름 바로 뒤에 <Type> 을 넣는다
// Set 생성자를 사용하여
var nameSet = Set<String>.from(names);

// Map 생성자를 사용하여
var views = Map<int, View>();

 

3. Generic collections and the types they contain

  • Dart 제네릭 타입이 수정되어 런타임 시 타입 정보를 전달한다
  • 반대로 Java 의 제네릭은 ensure 를 사용한다. 즉, 제네릭 타입 매개 변수가 런타임에 제거된다
  • Java 에서는 객체가 List 인지 여부를 테스트 할 수 있지만 List<String>인지 여부는 테스트 할 수 없다
var names = List<String>();
names.addAll(['Seth', 'Kathy', 'Lars']);
print(names is List<String>); // true

 

4. Restricting the parameterized type

  • 일반 타입을 구현할 때 해당 매개 변수의 타입을 extends 를 사용하여 제한 할 수 있다
class Foo<T extends SomeBaseClass> {
  // Implementation goes here...
  String toString() => "Instance of 'Foo<$T>'";
}

class Extender extends SomeBaseClass {...}

// 제네릭 인수 없이 생성 가능
var foo = Foo();
print(foo); // Foo<SomeBaseClass> 인스턴스

// SomeBaseClass 가 아닌 타입으로는 생성할 수 없다
var foo = Foo<Object>();

 

5. Using generic methods

  • 처음에 Dart의 제네릭 지원은 클래스로 제한되었었다
  • 제네릭 메서드라고 하는 최신 구문은 메서드 및 함수에 대한 타입 인수를 허용한다
  • 아래에서 first<T> 의 제네릭 타입 매개 변수를 사용하면 여러 위치에서 타입 인수 T 를 사용할 수 있다
    • 함수의 반환 타입도 T 로 사용할 수 있다
    • 인수 타입 List<T> 로 사용할 수 있다
    • 지역 변수 타입으로 T tmp 로 사용할 수 있다
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;
}

 

'기타개발 > Flutter' 카테고리의 다른 글

Dart #10 - Asychrony support, Generator  (0) 2020.08.28
Dart #9 : Library  (1) 2020.08.28
Dart #7 : Extension method, Enum, Mixin  (0) 2020.08.28
Dart #6 : Abstract, Implicit interface, Extends  (0) 2020.08.28
Dart #5 : Classes, Constructor  (0) 2020.08.28

댓글