46. 제너릭 사용하기: 제너릭 클래스를 정의하고 사용하는 예제
문제
제너릭 클래스를 정의하고, 다양한 타입으로 인스턴스를 생성하여 사용해보세요.
답변
// 제너릭 클래스 정의
class Box<T> {
T value;
Box(this.value);
T getValue() => value;
void setValue(T newValue) {
value = newValue;
}
}
void main() {
// 정수형 박스
Box<int> intBox = Box(42);
print('Integer value: ${intBox.getValue()}');
// 문자열형 박스
Box<String> stringBox = Box('Hello');
print('String value: ${stringBox.getValue()}');
// 더블형 박스
Box<double> doubleBox = Box(3.14);
print('Double value: ${doubleBox.getValue()}');
}
설명
Box<T>는 제너릭 클래스로, T는 데이터 타입을 나타내는 타입 파라미터입니다. 이를 통해 특정 타입에 제한되지 않는 다양한 객체를 저장할 수 있습니다. 예제에서는 정수, 문자열, 더블형으로 Box를 생성하고 사용했습니다.
47. 익명 함수 사용하기: 리스트의 각 요소를 변환
문제
익명 함수를 사용하여 리스트의 각 요소를 변환하세요.
답변
void main() {
List<int> numbers = [1, 2, 3, 4, 5];
// 익명 함수를 사용하여 각 요소를 제곱
List<int> squaredNumbers = numbers.map((number) => number * number).toList();
print(squaredNumbers); // [1, 4, 9, 16, 25]
}
설명
익명 함수(람다 함수)는 함수의 이름 없이 사용할 수 있는 함수를 의미합니다. 위 코드에서는 map 메서드를 사용하여 리스트의 각 요소를 익명 함수로 변환했습니다. 이 예제에서는 각 요소를 제곱한 값을 반환합니다.
48. 인터페이스 구현하기: 인터페이스 정의 및 구현
문제
인터페이스를 정의하고 이를 구현하는 클래스를 작성하세요.
답변
// 인터페이스 정의
abstract class Animal {
void speak();
}
// 인터페이스 구현 클래스
class Dog implements Animal {
@override
void speak() {
print('Bark!');
}
}
class Cat implements Animal {
@override
void speak() {
print('Meow!');
}
}
void main() {
Animal dog = Dog();
dog.speak(); // Bark!
Animal cat = Cat();
cat.speak(); // Meow!
}
설명
Animal은 메서드 speak를 정의하는 추상 클래스입니다. Dog와 Cat 클래스는 Animal 인터페이스를 구현하고, 각각의 방식으로 speak 메서드를 재정의합니다. 이를 통해 객체의 다형성을 실현할 수 있습니다.
49. 데이터 클래스 사용하기: 데이터 클래스 정의 및 사용
문제
데이터 클래스를 정의하고 사용하는 예제를 작성하세요.
답변
// 데이터 클래스 정의
class Person {
final String name;
final int age;
Person(this.name, this.age);
@override
String toString() => 'Person(name: $name, age: $age)';
}
void main() {
Person person = Person('John Doe', 30);
print(person); // Person(name: John Doe, age: 30)
}
설명
Person 클래스는 데이터 클래스의 예시입니다. name과 age라는 두 개의 필드를 가지며, 생성자를 통해 초기화됩니다.
toString 메서드를 오버라이드하여 객체의 문자열 표현을 제공합니다.
50. 미래와 스트림 결합하기: Future와 Stream을 결합하여 데이터 처리
문제
Future와 Stream을 결합하여 데이터를 처리하는 예제를 작성하세요.
답변
import 'dart:async';
// 비동기 함수 예제
Future<String> fetchData() async {
await Future.delayed(Duration(seconds: 2));
return 'Data fetched';
}
// Stream 예제
Stream<int> numberStream() async* {
for (int i = 1; i <= 5; i++) {
await Future.delayed(Duration(seconds: 1));
yield i;
}
}
void main() async {
// Future 사용
fetchData().then((data) {
print(data);
});
// Stream 사용
await for (int number in numberStream()) {
print(number);
}
}
설명
fetchData 함수는 Future를 반환하며, 비동기적으로 데이터를 가져옵니다.
numberStream 함수는 Stream을 반환하며, 1초 간격으로 숫자를 생성합니다.
Future와 Stream을 결합하여 데이터를 비동기적으로 처리할 수 있습니다.
이러한 다양한 기능은 Dart의 강력한 특징을 보여줍니다.
제너릭은 코드의 재사용성을 높이고, 익명 함수는 간결한 표현을 가능하게 하며, 인터페이스와 데이터 클래스는 구조적 프로그래밍을 지원합니다.
Future와 Stream은 비동기 프로그래밍을 쉽게 구현할 수 있도록 도와줍니다.
'Dart > Dart 100제' 카테고리의 다른 글
Dart 100제 61 ~ 65 (문자열과 정규 표현식) (0) | 2024.08.09 |
---|---|
Dart 100제 51 ~ 60 (보충 문제) (0) | 2024.08.09 |
Dart 100제 41 ~ 45 (알고리즘) (0) | 2024.08.07 |
Dart 100제 36 ~ 40 (비동기 프로그래밍) (2) | 2024.07.24 |
Dart 100제 31 ~ 35 (파일 입출력) (2) | 2024.07.24 |