제네릭 클래스
Coddy Dart 여정의 객체 지향 프로그래밍 섹션에 포함된 레슨 — 110개 중 65번째.
Dart의 List<String>과 같은 내장 컬렉션이 타입 매개변수를 어떻게 사용하는지 살펴보았습니다. 이제 여러분이 지정하는 어떤 타입과도 작동하는 여러분만의 제네릭 클래스를 직접 만들어 볼 차례입니다.
제네릭 클래스는 인스턴스를 생성할 때 제공될 실제 타입을 위한 플레이스홀더로 타입 매개변수(일반적으로 T)를 사용합니다:
class Box<T> {
T content;
Box(this.content);
T getContent() => content;
}
void main() {
var stringBox = Box<String>('Hello');
var intBox = Box<int>(42);
print(stringBox.getContent()); // Hello
print(intBox.getContent()); // 42
}T는 타입 변수 역할을 합니다. Box<String>을 생성할 때, 클래스 내의 모든 T는 String이 됩니다. 이는 각 타입에 대해 별도의 클래스를 작성하지 않고도 타입 안정성을 제공합니다.
클래스가 둘 이상의 타입을 처리해야 할 때 여러 개의 타입 매개변수를 사용할 수 있습니다:
class Pair<K, V> {
K first;
V second;
Pair(this.first, this.second);
}
void main() {
var pair = Pair<String, int>('age', 25);
print('${pair.first}: ${pair.second}'); // age: 25
}제네릭 클래스는 재사용 가능하고 타입 안전한 코드의 기초입니다. 서로 다른 타입에 대해 로직을 중복 작성하거나 dynamic을 사용하여 타입 정보를 잃는 대신, 제네릭을 사용하면 컴파일러가 여전히 검증할 수 있는 유연한 코드를 작성할 수 있습니다.
챌린지
쉬움다양한 유형의 아이템을 위한 유연한 컨테이너를 만들기 위해 제네릭 클래스를 사용하는 선물 포장 시스템을 구축해 보겠습니다. 어떤 유형의 내용물도 포장할 수 있는 제네릭 Wrapper 클래스와, 선물과 카드 메시지를 쌍으로 묶기 위해 두 개의 타입 매개변수를 가진 GiftBox 클래스를 만들 것입니다.
코드를 두 개의 파일로 구성합니다:
wrapper.dart: 여기에 제네릭 클래스들을 정의하세요:T content속성과 생성자를 가진 제네릭 클래스Wrapper<T>. 내용물을 반환하는unwrap()메서드와,Wrapped: [content]를 출력하는describe()메서드를 포함하세요.- 두 개의 속성
G gift와C card를 가진 제네릭 클래스GiftBox<G, C>. 생성자와 함께, 첫 번째 줄에Gift: [gift]를 출력하고 다음 줄에Card: [card]를 출력하는open()메서드를 포함하세요.
main.dart: wrapper 파일을 임포트하고 다양한 타입을 사용하여 제네릭 클래스들을 시연하세요:'Chocolate'을 포함하는Wrapper<String>을 생성하고describe()를 호출하세요.42를 포함하는Wrapper<int>를 생성하고describe()를 호출하세요.3.14를 포함하는Wrapper<double>을 생성하고describe()를 호출하세요.- 빈 줄을 출력하세요.
- 선물
'Teddy Bear'와 카드'Happy Birthday!'를 가진GiftBox<String, String>을 생성한 후open()을 호출하세요. - 빈 줄을 출력하세요.
- 선물
100(기프트 카드 금액을 나타냄)과 카드'Congratulations!'를 가진GiftBox<int, String>을 생성한 후open()을 호출하세요.
동일한 Wrapper 클래스가 문자열, 정수, 실수와 어떻게 원활하게 작동하는지 확인해 보세요. GiftBox 클래스는 두 개의 타입 매개변수를 사용하여 서로 다른 타입을 쌍으로 묶는 방법을 보여줍니다. 선물은 어떤 타입이든 될 수 있는 반면 카드 메시지는 문자열로 유지됩니다.
예상 출력:
Wrapped: Chocolate
Wrapped: 42
Wrapped: 3.14
Gift: Teddy Bear
Card: Happy Birthday!
Gift: 100
Card: Congratulations!치트 시트
제네릭 클래스는 인스턴스를 생성할 때 지정되는 실제 타입에 대한 플레이스홀더로 타입 매개변수(예: T)를 사용합니다:
class Box<T> {
T content;
Box(this.content);
T getContent() => content;
}
void main() {
var stringBox = Box<String>('Hello');
var intBox = Box<int>(42);
print(stringBox.getContent()); // Hello
print(intBox.getContent()); // 42
}Box<String>을 생성하면 클래스 내의 모든 T가 String이 되어, 각 타입별로 별도의 클래스를 만들지 않고도 타입 안전성을 제공합니다.
둘 이상의 타입을 다룰 때는 여러 개의 타입 매개변수를 사용하세요:
class Pair<K, V> {
K first;
V second;
Pair(this.first, this.second);
}
void main() {
var pair = Pair<String, int>('age', 25);
print('${pair.first}: ${pair.second}'); // age: 25
}직접 해보기
import 'wrapper.dart';
void main() {
// TODO: 'Chocolate'를 포함하는 Wrapper<String>을 생성하고 describe()를 호출하세요
// TODO: 42를 포함하는 Wrapper<int>를 생성하고 describe()를 호출하세요
// TODO: 3.14를 포함하는 Wrapper<double>을 생성하고 describe()를 호출하세요
// TODO: 빈 줄을 출력하세요
// TODO: gift가 'Teddy Bear'인 GiftBox<String, String>을 생성하고
// card가 'Happy Birthday!'인 것을 확인한 후 open()을 호출하세요
// TODO: 빈 줄을 출력하세요
// TODO: gift가 100인 GiftBox<int, String>을 생성하고
// card가 'Congratulations!'인 것을 확인한 후 open()을 호출하세요
}
이 레슨에는 짧은 퀴즈가 포함되어 있습니다. 레슨을 시작해 문제를 풀고 진행 상황을 기록하세요.