Generics(제네릭)는 특정 타입에 구애받지 않고 다양한 데이터를 처리할 수 있도록 하는 기능입니다.
제네릭을 사용하면 코드의 재사용성이 높아지고, 타입 안정성이 보장됩니다.
Flutter에서는 제네릭을 사용하여 다양한 위젯이나 데이터 구조를 더 유연하게 설계할 수 있습니다.
1. Generics란?
Generics는 다양한 데이터 타입을 다룰 수 있는 일반적인 코드 구조를 의미합니다.
예를 들어, Dart의 List 클래스는 제네릭을 사용하여 숫자, 문자열, 위젯 등 모든 타입의 데이터를 담을 수 있습니다.
예시: 리스트(List)
List<int> numbers = [1, 2, 3]; // 정수 리스트
List<String> words = ["hello", "world"]; // 문자열 리스트
List<Widget> widgets = [Text("Hello"), Text("World")]; // 위젯 리스트
위 예시에서 List<int>는 정수만, List<String>은 문자열만, List<Widget>은 Flutter 위젯만 담을 수 있는 리스트입니다.
이처럼 제네릭을 사용하면 리스트가 담을 수 있는 데이터의 타입을 유연하게 지정할 수 있습니다.
2. 제네릭 클래스 만들기
Flutter에서도 제네릭 클래스를 활용할 수 있습니다.
제네릭 클래스를 사용하면 하나의 클래스가 여러 데이터 타입을 처리할 수 있어, 코드 재사용성이 높아집니다.
예시: 제네릭 클래스
class Storage<T> {
T? _item;
void setItem(T item) {
_item = item;
}
T? getItem() {
return _item;
}
}
void main() {
Storage<int> intStorage = Storage<int>();
intStorage.setItem(100);
print(intStorage.getItem()); // 100
Storage<String> stringStorage = Storage<String>();
stringStorage.setItem("Hello Flutter");
print(stringStorage.getItem()); // Hello Flutter
}
위 예시에서 Storage<T>는 제네릭 클래스로, 데이터 타입 T에 따라 다양한 타입의 데이터를 저장할 수 있습니다.
Storage<int>는 정수를 저장하고, Storage<String>은 문자열을 저장할 수 있습니다.
3. 제네릭 함수 만들기
제네릭 함수는 여러 타입의 데이터를 처리할 수 있는 함수를 의미합니다.
함수의 매개변수나 반환값의 타입을 제네릭으로 정의할 수 있습니다.
예시: 제네릭 함수
T getFirst<T>(List<T> items) {
return items[0];
}
void main() {
print(getFirst<int>([1, 2, 3])); // 1
print(getFirst<String>(["apple", "banana", "cherry"])); // apple
print(getFirst<bool>([true, false])); // true
}
위 예시에서 getFirst<T> 함수는 제네릭 타입 T를 사용하여 리스트의 첫 번째 요소를 반환합니다.
이 함수는 정수, 문자열, 불리언 등 다양한 타입의 데이터를 처리할 수 있습니다.
4. Flutter에서 제네릭 사용 예시
Flutter에서 제네릭을 사용하면 UI를 더 유연하게 만들 수 있습니다.
대표적으로 FutureBuilder 위젯은 제네릭을 사용하여 비동기 작업의 결과 타입을 지정할 수 있습니다.
예시: FutureBuilder
Future<String> fetchGreeting() async {
await Future.delayed(Duration(seconds: 2));
return "Hello, Flutter!";
}
class MyWidget extends StatelessWidget {
@override
Widget build(BuildContext context) {
return FutureBuilder<String>(
future: fetchGreeting(),
builder: (BuildContext context, AsyncSnapshot<String> snapshot) {
if (snapshot.connectionState == ConnectionState.waiting) {
return CircularProgressIndicator(); // 로딩 중
} else if (snapshot.hasError) {
return Text('Error: ${snapshot.error}'); // 에러 발생 시
} else {
return Text('Greeting: ${snapshot.data}'); // 데이터 표시
}
},
);
}
}
위 코드에서 FutureBuilder<String>은 제네릭을 사용하여 비동기 작업의 결과가 문자열(String)임을 명시합니다.
fetchGreeting() 함수는 2초 후에 "Hello, Flutter!"라는 문자열을 반환하고, 이 결과는 FutureBuilder를 통해 UI에 표시됩니다.
5. 제네릭의 장점
- 유연성: 다양한 타입의 데이터를 처리할 수 있어, 코드 작성 시 유연하게 사용할 수 있습니다.
- 재사용성: 제네릭 클래스를 사용하면 동일한 로직을 여러 타입에 적용할 수 있어, 코드의 재사용성이 높아집니다.
- 타입 안전성: 컴파일 시 타입 검사를 통해 타입 안전성을 보장하여, 런타임 오류를 줄일 수 있습니다.
마치며
이번 포스트에서는 Flutter에서 Generics를 쉽게 이해할 수 있도록 설명했습니다.
제네릭은 다양한 타입의 데이터를 처리할 수 있게 해주는 강력한 도구로, Flutter 앱 개발에서 자주 사용됩니다.
제네릭을 이해하고 활용하면 코드의 유연성과 재사용성을 높일 수 있습니다.
Starting Google Play App Distribution! "Tester Share" for Recruiting 20 Testers for a Closed Test.
'Flutter' 카테고리의 다른 글
플러터에서 MediaQuery와 Orientation 사용법: 초보자도 쉽게 이해할 수 있는 가이드 (0) | 2024.08.06 |
---|---|
코드 간결하게 작성하기: 플러터 표현식 정리 (0) | 2024.08.06 |
플러터에서 콜백 함수란? 이해하고 활용하기 (0) | 2024.08.01 |
플러터에서 Future와 void, 언제 어떻게 사용해야 할까요? (0) | 2024.07.31 |
플러터에서 Event Loop 구현하기 (0) | 2024.07.31 |