Dart 학습: 고급 주제
Dart의 고급 기능을 활용하면 더 강력하고 유연한 코드를 작성할 수 있습니다. 이번 글에서는 제너릭, 믹스인, 메타프로그래밍(리플렉션과 어노테이션)에 대해 알아보겠습니다.
1. 제너릭: 제너릭 클래스와 함수
제너릭(Generics)은 데이터 타입을 일반화하여 코드 재사용성을 높이는 방법입니다. 제너릭을 사용하면 타입 안정성을 유지하면서 다양한 데이터 타입을 처리할 수 있습니다.
제너릭 클래스: 제너릭 클래스를 사용하면 클래스가 다양한 데이터 타입을 처리할 수 있습니다.
T value;
Box(this.value);
void display() {
print('Value: $value');
}
}
void main() {
Box<int> intBox = Box<int>(123);
intBox.display(); // Value: 123 출력
Box<String> strBox = Box<String>('Hello, Dart');
strBox.display(); // Value: Hello, Dart 출력
}
위의 예제에서 Box 클래스는 제너릭 타입 T를 사용하여 다양한 데이터 타입을 처리할 수 있습니다. int와 String 타입의 Box 객체를 각각 생성하여 사용합니다.
제너릭 함수: 제너릭 함수를 사용하면 함수가 다양한 데이터 타입을 처리할 수 있습니다.
return a + b;
}
void main() {
print(add<int>(2, 3)); // 5 출력
print(add<double>(2.5, 3.5)); // 6.0 출력
}
위의 예제에서 add 함수는 제너릭 타입 T를 사용하여 숫자 타입의 값을 더할 수 있습니다. int와 double 타입의 값을 더하는 데 사용됩니다.
2. 믹스인: 믹스인 사용법
믹스인(Mixin)은 여러 클래스의 기능을 한 클래스에 혼합할 수 있는 방법입니다. 믹스인은 상속과 유사하지만, 상속보다 더 유연하게 사용할 수 있습니다.
믹스인 사용 예제:
void fly() {
print('Flying');
}
}
mixin Swim {
void swim() {
print('Swimming');
}
}
class Duck with Fly, Swim {
void display() {
print('I am a duck');
}
}
void main() {
Duck duck = Duck();
duck.display(); // I am a duck 출력
duck.fly(); // Flying 출력
duck.swim(); // Swimming 출력
}
위의 예제에서 Fly와 Swim 믹스인은 각각 fly와 swim 메서드를 제공합니다. Duck 클래스는 with 키워드를 사용하여 두 믹스인을 혼합하여 사용할 수 있습니다.
3. 메타프로그래밍: 리플렉션과 어노테이션
메타프로그래밍은 프로그램이 자신의 구조나 동작을 검사하고 수정할 수 있는 프로그래밍 기법입니다. Dart에서는 리플렉션(reflection)과 어노테이션(annotation)을 사용하여 메타프로그래밍을 구현할 수 있습니다.
리플렉션: 리플렉션은 객체의 타입, 메서드, 필드 등을 런타임에 검사하고 조작할 수 있는 기능입니다. Dart에서는 dart:mirrors 라이브러리를 사용하여 리플렉션을 구현할 수 있습니다.
리플렉션 예제:
class Person {
String name;
int age;
Person(this.name, this.age);
void greet() {
print('Hello, my name is $name and I am $age years old.');
}
}
void main() {
Person person = Person('Alice', 25);
// 리플렉션을 사용하여 객체의 메서드 호출
InstanceMirror im = reflect(person);
ClassMirror cm = im.type;
cm.declarations.forEach((symbol, declaration) {
if (declaration is MethodMirror && declaration.simpleName == Symbol('greet')) {
im.invoke(declaration.simpleName, []);
}
});
}
위의 예제에서 reflect 함수를 사용하여 객체의 인스턴스를 검사하고, invoke 메서드를 사용하여 greet 메서드를 런타임에 호출합니다.
어노테이션: 어노테이션은 메타데이터를 클래스, 메서드, 필드 등에 추가할 수 있는 기능입니다. Dart에서는 @ 기호를 사용하여 어노테이션을 정의할 수 있습니다.
어노테이션 예제:
final String description;
const MyAnnotation(this.description);
}
@MyAnnotation('This is a person class')
class Person {
String name;
int age;
Person(this.name, this.age);
@MyAnnotation('This is a greet method')
void greet() {
print('Hello, my name is $name and I am $age years old.');
}
}
void main() {
// 어노테이션을 리플렉션을 통해 검사
ClassMirror cm = reflectClass(Person);
cm.metadata.forEach((meta) {
MyAnnotation annotation = meta.reflectee as MyAnnotation;
print('Class annotation: ${annotation.description}');
});
cm.declarations.forEach((symbol, declaration) {
if (declaration is MethodMirror) {
declaration.metadata.forEach((meta) {
MyAnnotation annotation = meta.reflectee as MyAnnotation;
print('Method annotation: ${annotation.description}');
});
}
});
}
위의 예제에서 MyAnnotation 어노테이션을 정의하고, Person 클래스와 greet 메서드에 어노테이션을 추가합니다. reflectClass 함수를 사용하여 어노테이션을 검사하고 출력합니다.
이 글에서는 Dart의 고급 주제인 제너릭, 믹스인, 메타프로그래밍(리플렉션과 어노테이션)에 대해 알아보았습니다. 이러한 고급 기능을 이해하고 활용하면 더 강력하고 유연한 코드를 작성할 수 있습니다. Happy Coding!
'프로그래밍 > Dart' 카테고리의 다른 글
[Dart] 12. Dart의 "Flutter 소개" (0) | 2024.06.21 |
---|---|
[Dart] 11. Dart의 "웹 개발" (0) | 2024.06.19 |
[Dart] 9. Dart의 "라이브러리와 패키지" (0) | 2024.06.19 |
[Dart] 8. Dart의 "파일 입출력" (0) | 2024.06.19 |
[Dart] 7. Dart의 "비동기 프로그래밍" (0) | 2024.06.19 |