[Dart] ์๋ฐ์คํฌ๋ฆฝํธ ๊ฐ๋ฐ์์ ๋คํธ ํ์ต - Part 2
Dart์ JavaScript๋ ๋ง์ ๊ฐ๋ ์ ๊ณต์ ํ๋ค. Dart ์ญ์ ์ด๋ฒคํธ ๋ฃจํ์์ ์คํ๋๊ณ , ๋น๋๊ธฐ ํ๋ก๊ทธ๋๋ฐ์ ์ํ Future๋ผ๋ ๊ฐ๋ ์ด ์กด์ฌํ๋ค. Future๋ ์๋ฐ์คํฌ๋ฆฝํธ์ Promise์ ๋น์ทํ๋ค. Dart๋ ์ ์ ํ์ ์ธ์ด์ด๊ธฐ ๋๋ฌธ์ ํ์ ์คํฌ๋ฆฝํธ๋ฅผ ์ฌ์ฉํ ๊ฒฝํ์ด ์๋ค๋ฉด Dart๋ฅผ ๋ ์ฝ๊ฒ ๋ฐฐ์ธ ์ ์๋ค.
Dart์ JavaScript์ ๋ค๋ฅธ ์ ๊ณผ ๋น์ทํ ์ ์ Learning Dart as a JavaScript developer ํ์ด์ง์ ์์ธํ ์ค๋ช ๋ผ ์์ด์ ์ ๋ฆฌํด๋ดค๋ค.
๐ก ์๋๋ Part 1์์ ์ด์ด์ง๋ Part 2 ๋ด์ฉ.
Asynchrony
์๋ฐ์คํฌ๋ฆฝํธ์ ๋ง์ฐฌ๊ฐ์ง๋ก Dart ๊ฐ์๋จธ์ (VM)์ ๋จ์ผ ์ด๋ฒคํธ ๋ฃจํ๋ฅผ ์ฌ์ฉํ์ฌ ์ฝ๋๋ฅผ ์คํํ๋ค. ๋ชจ๋ ์ฝ๋๋ ๋๊ธฐ์ ์ผ๋ก ์คํ๋์ง๋ง, ๋น๋๊ธฐ ๋๊ตฌ๋ฅผ ํตํด ์คํ ์์๋ฅผ ์ ์ดํ ์ ์๋ค.
Futures
์๋ฐ์คํฌ๋ฆฝํธ์ Promise๊ฐ ์๋ค๋ฉด Dart์ Future๊ฐ ์๋ค. ์๋ ๋ฐฉ์ ์ญ์ ๋น์ทํ๋ค.
// JS
const httpResponseBody = func();
httpResponseBody.then((value) => {
console.log(`Promise resolved to a value: ${value}`);
});
// Dart
Future<String> httpResponseBody = func();
httpResponseBody.then((String value) {
print('Future resolved to a value: $value');
});
Futures๋ ํ๋ก๋ฏธ์ค์ฒ๋ผ ์คํจํ ์ ์๊ณ catchError
๋ฉ์๋๋ฅผ ํตํด ์ค๋ฅ๋ฅผ ์ฒ๋ฆฌํ ์ ์๋ค.
// JS
httpResponseBody
.then(...)
.catch(err => {
console.log(
"Promise encountered an error before resolving."
);
});
// Dart
httpResponseBody
.then(...)
.catchError((err) {
print(
'Future encountered an error before resolving.'
);
});
Promise.resolve()
์ฒ๋ผ ์ฆ์ ์๋ฃ๋๋ Future๋ฅผ ์์ฑํ ์๋ ์๋ค.
String str = 'String Value';
Future<String> strFuture = Future<String>.value(str);
strFuture.then(print); // String Value
Async/Await
Dart๋ Async/Await ๊ตฌ๋ฌธ์ ์ง์ํ๋ฉฐ ์๋ฐ์คํฌ๋ฆฝํธ์ฒ๋ผ async
ํค์๋๋ฅผ ์ฌ์ฉํ ํจ์๋ Future๋ฅผ ๋ฐํํ๋ค. ์๋ฅผ๋ค์ด String์ ๋ฐํํ๋ ํจ์์ async
๋ฅผ ์ถ๊ฐํ๋ค๋ฉด Future<String>
์ ๋ฐํํ๋ค.
// Promise<string> ๋ฐํ
async function fetchString() {
return "String Value";
}
fetchString().then((str) => {
console.log(str); // String Value
});
// Future<String> ๋ฐํ
Future<String> fetchString() async {
return 'String Value';
}
fetchString().then((String str) {
print(str); // String Value
});
then()
๋์ await
ํค์๋๋ฅผ ์ด์ฉํด์ Future ๊ฐ์ ์ป์ ์ ์๋ค. ์๋ฐ์คํฌ๋ฆฝํธ์ ๋ง์ฐฌ๊ฐ์ง๋ก await
ํค์๋๋ async
ํจ์ ๋ด์์๋ง ์ฌ์ฉํ ์ ์๋ค.
// await๋ async ์ปจํ
์คํธ์์๋ง ์ฌ์ฉํ ์ ์๋ค.
Future<void> asyncFunction() async {
var str = await fetchString();
print(str); // 'String Value'
}
Streams
- Dart์์ rxjs ๋ผ์ด๋ธ๋ฌ๋ฆฌ์์ ์ ๊ณตํ๋ Observable๊ณผ ์ ์ฌํ ์คํธ๋ฆผ์ ์ ๊ณตํ๋ค.
- ์คํธ๋ฆผ์ ๊ธฐ๋ณธ์ ์ผ๋ก Future์ ์ ์ฌํ์ง๋ง ์๊ฐ์ ๋ฐ๋ผ ์ฌ๋ฌ ๊ฐ์ ์ ๋ฌํ๋ ์ด๋ฒคํธ ๋ฒ์ค(event bus)์ฒ๋ผ ๋์ํ๋ค. ์คํธ๋ฆผ์ ์์ ์ด ๊ฐ๋ฅํ๊ณ , ์๋ฃ ํน์ ์คํจ ์ํ์ ๋๋ฌํ ์ ์๋ค.
Listening
์คํธ๋ฆผ์ด ๊ฐ์ ์ ์กํ ๋๋ง๋ค ํด๋น ์คํธ๋ฆผ์ listen
๋ฉ์๋๊ฐ ํธ์ถ๋๋ค.
Stream<int> stream = ...
stream.listen((int value) {
print('A value has been emitted: $value');
});
listen
๋ฉ์๋๋ ์ค๋ฅ ์ฒ๋ฆฌ ํน์ ์๋ฃ๋ฅผ ์ํ ์ ํ์ ์ฝ๋ฐฑ์ ํฌํจํ๋ค.
stream.listen(
// onData: ์คํธ๋ฆผ์ด ์๋ก์ด ๋ฐ์ดํฐ๋ฅผ ์ ์กํ ๋ ํธ์ถ
(int value) {
// ๋ฐ์ดํฐ ์ฒ๋ฆฌ ๋ก์ง
},
// onError: ์คํธ๋ฆผ์์ ์ค๋ฅ๊ฐ ๋ฐ์ํ์ ๋ ํธ์ถ
onError: (err) {
print('Stream encountered an error! $err');
},
// onDone: ์คํธ๋ฆผ์ด ์๋ฃ๋์ ๋ ํธ์ถ
onDone: () {
print('Stream completed!');
},
);
listen
๋ฉ์๋๋ StreamSubscription
์ธ์คํด์ค๋ฅผ ๋ฐํํ๊ณ , ์ด ์ธ์คํด์ค๋ฅผ ํตํด ์คํธ๋ฆผ ์์ ์ ์ค์งํ ์ ์๋ค.
StreamSubscription subscription = stream.listen(...);
subscription.cancel();
๋น๋๊ธฐ ์ปจํ ์คํธ(async ํจ์) ์์์ ์คํธ๋ฆผ๊ณผ for-in ๋ฃจํ๋ฅผ ๊ฒฐํฉํ ์๋ ์๋ค.
Future<int> sumStream(Stream<int> stream) async {
var sum = 0;
await for (final value in stream) {
sum += value;
}
return sum;
}
try-catch ๋ฌธ์ผ๋ก ์คํธ๋ฆผ ์์ ์๋ฌ๋ฅผ ์บ์นํ ์ ์๋ค.
try {
await for (final value in stream) { ... }
} catch (err) {
print('Stream encountered an error! $err');
}
Creating streams
Stream ํด๋์ค๋ ์คํธ๋ฆผ์ ์์ฑํ๋ ๋ค์ํ ๋ฐฉ๋ฒ์ ์ ๊ณตํ๋ค.
Stream.fromFuture
๋ฅผ ์ฌ์ฉํ์ฌ Future๋ฅผ ๊ธฐ๋ฐ์ผ๋ก ์คํธ๋ฆผ์ ์์ฑํ ์ ์๋ค.
Stream.fromIterable
์ ์ฌ์ฉํ์ฌ Iterable ์ปฌ๋ ์
์ ์คํธ๋ฆผ์ผ๋ก ๋ณํํ ์ ์๋ค.
Stream.periodic
์ ์ฌ์ฉํ์ฌ ์ผ์ ๊ฐ๊ฒฉ์ผ๋ก ๊ฐ์ ์ ์กํ๋ ์คํธ๋ฆผ์ ์์ฑํ ์ ์๋ค.
StreamController
๋ฅผ ์ฌ์ฉํ์ฌ ์คํธ๋ฆผ์ ์์ฑํ๊ณ , ๋ฆฌ์ค๋๊ฐ ์ถ๊ฐ๋ ๋๋ง๋ค ํน์ ๋์์ ์ํํ๋๋ก ํ ์ ์๋ค.
var listeners = 0; // ๋ฆฌ์ค๋ ๊ฐ์๋ฅผ ์ถ์ ํ๋ ๋ณ์
StreamController<int>? controller; // ์ปจํธ๋กค๋ฌ ์ ์ธ
controller = StreamController<int>(
// ์๋ก์ด ๋ฆฌ์ค๋๊ฐ ์คํธ๋ฆผ์ ๊ตฌ๋
ํ ๋๋ง๋ค ๋ฉ์๋ ํธ์ถ
onListen: () {
// listeners ๊ฐ์ ์ฆ๊ฐ์ํค๊ณ ํด๋น ๊ฐ์ ๋ฆฌ์ค๋์๊ฒ ์ ์ก
controller!.add(++listeners);
// 5๋ฒ์งธ ๋ฆฌ์ค๋ ์ดํ์๋ ์คํธ๋ฆผ์ ๋ซ์
if (listeners > 5) controller.close();
}
);
// ์คํธ๋ฆผ ์ปจํธ๋กค๋ฌ์์ ์คํธ๋ฆผ ๊ฐ์ ธ์ค๊ธฐ
var stream = controller.stream;
// ์คํธ๋ฆผ ๊ตฌ๋
stream.listen((int value) {
print('$value'); // 1
});
ํจ์์ sync*
ํค์๋๋ฅผ ๋ถ์ด๋ฉด ๋๊ธฐ์ ์ ๋๋ ์ดํฐ๊ฐ ๋๋ฉฐ ์ด ํจ์๋ ์ดํฐ๋ฌ๋ธ์ ๋ฐํํ๋ค. ํจ์์ async*
๋ฅผ ๋ถ์ด๋ฉด ๋น๋๊ธฐ ์ ๋๋ ์ดํฐ๊ฐ ๋๊ณ ์ด ํจ์๋ ์คํธ๋ฆผ์ ๋ฐํํ๋ค. ๋น๋๊ธฐ ์ ๋๋ ์ดํฐ์์ yield
๋ ์ฃผ์ด์ง ๊ฐ์ ์คํธ๋ฆผ์ ์ ๋ฌํ๋ค.
Stream<int> asyncNaturalsTo(int n) async* {
var k = 0;
while (k < n) {
yield k++;
}
}
Stream<int> stream1 = asyncNaturalsTo(5);
stream1.listen(print); // 0, 1, 2, 3, 4
Stream<int> stream2 = asyncNaturalsTo(5);
// stream์ forEach ๋ฉ์๋๋ ์ ๊ณตํ๋ค
// yield ๋ ๋๋ง๋ค forEach์ ์ฝ๋ฐฑ์ด ์คํ๋๋ค
stream2.forEach(print); // 0, 1, 2, 3, 4
๋น๋๊ธฐ ์ ๋๋ ์ดํฐ์์ yield*
๋ฅผ ์ฌ์ฉํ๋ฉด ๋ค๋ฅธ ๋น๋๊ธฐ ์ ๋๋ ์ดํฐ์ ๋ชจ๋ ๊ฐ์ ํ์ฌ ์คํธ๋ฆผ์ ์์ฐจ์ ์ผ๋ก yield
ํ ์ ์๋ค.
Classes
Dart์ ์๋ฐ์คํฌ๋ฆฝํธ์ ํด๋์ค๋ ์ ์ฌํด๋ณด์ด์ง๋ง ์๋ฐ์คํฌ๋ฆฝํธ์ ํด๋์ค๋ ๊ธฐ์ ์ ์ผ๋ก ํ๋กํ ํ์ ์ ๊ฐ์ธ๋ ๋ํผ(Wrapper)์ ๊ฐ๊น๋ค. ๋ฐ๋ฉด, Dart์ ํด๋์ค๋ ์ธ์ด์ ํ์ค ๊ธฐ๋ฅ์ด๋ค.
"this" context
- Dart์ this๋ ํจ์๋ฅผ ๋ฐ์ธ๋ฉ ํ ์ ์๊ณ , ์คํ ์ปจํ ์คํธ์ ์์กดํ์ง ์๋๋ค.
- Dart์ this๋ ํด๋์ค์์๋ง ์ฌ์ฉ๋๋ฉฐ, ํญ์ ํ์ฌ ์ธ์คํด์ค๋ฅผ ์ฐธ์กฐํ๋ค.
Constructors
Standard constructor
Dart์ ํ์ค ํด๋์ค ์์ฑ์๋ ์ ์ฒด ํด๋์ค ์ด๋ฆ์ ์ฌ์ฉํ๋ค. ์์ฑ์์ ๋ชจ๋ ๋งค๊ฐ๋ณ์์ ํ์
์ ๋ช
์์ ์ผ๋ก ์ง์ ํ๋ ๊ฒ์ด ์ข๋ค. ํด๋์ค์ ์ธ์คํด์ค๋ฅผ ์์ฑํ ๋ new
ํค์๋๋ฅผ ๋ถ์ด์ง ์์๋ ๋๋ค.
class Point {
// ํด๋์ค ํ๋ (์ธ์คํด์ค ์์ฑ ์ ์)
final double x;
final double y;
// ํ์ค ์์ฑ์ ": this.x = x, this.y = y" ๋ถ๋ถ์ ์ด๊ธฐํ ๋ฆฌ์คํธ
Point(double x, double y) : this.x = x, this.y = y;
}
// Point ์ธ์คํด์ค ์์ฑ
Point p = Point(3, 5);
Initializer lists
์ด๊ธฐํ ๋ฆฌ์คํธ๋ ์์ฑ์๊ฐ ๋งค๊ฐ๋ณ์๋ก ๋ฐ์ ๊ฐ์ ํด๋์ค ํ๋์ ํ ๋นํ๋ ์์
์ด๋ค. ์ด๊ธฐํ ๋ฆฌ์คํธ๋ ์์ฑ์ ๋งค๊ฐ๋ณ์์ ๋ณธ๋ฌธ ์ฌ์ด์ ์ฝ์
ํ๋ค. ์ฝ๋ก :
๋ค์ ์ผํ๋ก ๊ตฌ๋ถํ์ฌ ์ฌ๋ฌ ์ด๊ธฐํ๋ฅผ ๋์ดํ ์ ์๋ค. ์ด๊ธฐํ ๋งค๊ฐ๋ณ์๋ฅผ ์ฌ์ฉํ์ฌ ์ด๊ธฐํ๋ฅผ ๋ ๊ฐ๋จํ๊ฒ ์์ฑํ ์ ์๋ค(๋ฌธ๋ฒ์ ์คํ).
// ์ด๊ธฐํ ๋งค๊ฐ๋ณ์๋ฅผ ์ฌ์ฉํ์ง ์์์ ๋
Point(double x, double y): this.x = x, this.y = y {}
// ์ด๊ธฐํ ๋งค๊ฐ๋ณ์๋ฅผ ์ฌ์ฉํ์ ๋
Point(this.x, this.y) {...}
์์ฑ์์์ ์์น ์ง์ ํน์ ์ด๋ฆ ์ง์ ๋งค๊ฐ๋ณ์๋ฅผ ๋ชจ๋ ์ฌ์ฉํ ์ ์๋ค.
class Point {
...
// ์ ํ์ ์์น ์ง์ ๋งค๊ฐ๋ณ์๋ฅผ ์ฌ์ฉํ๋ ์์ฑ์
Point(this.x, [this.y = 5]);
// ์ด๋ฆ ์ง์ ๋งค๊ฐ๋ณ์๋ฅผ ์ฌ์ฉํ๋ ์์ฑ์
Point({ required this.y, this.x = 5 });
// ์์น ์ง์ , ์ด๋ฆ ์ง์ ๋งค๊ฐ๋ณ์๋ฅผ ๋ชจ๋ ์ฌ์ฉํ๋ ์์ฑ์
Point(int x, int y, { boolean multiply }) {
...
}
...
}
Named constructors
Dart์์ ์๋ฐ์คํฌ๋ฆฝํธ์ ๋ฌ๋ฆฌ ์์ฑ์๋ฅผ ์ฌ๋ฌ๊ฐ ์ ์ํ ์ ์๋ค. Dart์์ 1๊ฐ์ ์ด๋ฆ ์๋(unnamed) ์์ฑ์์, ์ฌ๋ฌ๊ฐ์ ์ด๋ฆ ์๋(named) ์์ฑ์๋ฅผ ์ ์ํ ์ ์๋ค. ์ด๋ฆ ์๋ ์์ฑ์๋ ํด๋์ค ์ด๋ฆ ๋ค์ .
์จ์ ๊ณผ ์ํ๋ ์ด๋ฆ์ ๋ถ์ฌ์ ์ ์ํ๋ค.
class Person {
String name;
int age;
// ์ด๋ฆ ์๋ ์์ฑ์
Person(this.name, this.age);
// onlyName ์ด๋ฆ ์๋ ์์ฑ์
Person.onlyName(this.name, [this.age = 0]);
// defaultPerson ์ด๋ฆ ์๋ ์์ฑ์
Person.defaultPerson([this.name = "John", this.age = 30]);
}
void main() {
final p1 = Person("Zoe", 30);
final p2 = Person.onlyName("Jane");
final p3 = Person.defaultPerson();
}
Const constructor
์์ฑ์ ์์ const
ํค์๋๋ฅผ ๋ถ์ด๋ฉด ํด๋น ํด๋์ค์ ๋ชจ๋ ์ธ์คํด์ค ๋ณ์๋ final ์ด์ด์ผ ํ๋ค. ์ฆ, ์ธ์คํด์ค๊ฐ ํ ๋ฒ ์ด๊ธฐํ๋๋ฉด ์์ฑ์ ๋ณ๊ฒฝํ ์ ์๋ค.
class Point {
final int x;
final int y;
const Point(this.x, this.y);
}
void main() {
Point point = Point(1, 2);
point.x = 3; // Error! final ๋ณ์๋ ๋ณ๊ฒฝ ๋ถ๊ฐ
}
Constructor redirection
์์ฑ์ ๋งค๊ฐ๋ณ์ ๋ค์ ์ฝ๋ก (:
)๊ณผ this
ํค์๋๋ฅผ ์ฌ์ฉํ๋ฉด ๊ฐ์ ํด๋์ค์ ๋ค๋ฅธ ์์ฑ์๋ฅผ ํธ์ถํ ์ ์๋ค. ์ด๋ฅผ ์์ฑ์ ์์(๋๋ ์์ฑ์ ์ฒด์ด๋)์ด๋ผ๊ณ ๋ถ๋ฅธ๋ค.
class Point {
double x, y;
// ๋ฉ์ธ ์์ฑ์
Point(this.x, this.y);
// ๋ฉ์ธ ์์ฑ์๋ฅผ ํธ์ถํ๋ ์๋ธ ์์ฑ์
Point.alongXAxis(double x) : this(x, 0);
}
์์ฑ์ ์์์ ์ฌ์ฉํ๋ฉด ์ฝ๋ ์ค๋ณต์ ์ค์ด๊ณ ์์ฑ์ ๋ก์ง์ ๋ ํจ์จ์ ์ผ๋ก ๊ด๋ฆฌํ ์ ์๋ค.
Factory constructors
ํฉํ ๋ฆฌ ์์ฑ์๋ ๊ธฐ์กด ์ธ์คํด์ค๋ฅผ ๋ฐํํ๊ฑฐ๋ ํ์ ํ์ ์ ์ธ์คํด์ค๋ฅผ ์์ฑํ ์ ์๋ ํน๋ณํ ์์ฑ์๋ค. ์ผ๋ฐ ์์ฑ์์ ๋ฌ๋ฆฌ ํญ์ ์๋ก์ด ์ธ์คํด์ค๋ฅผ ์์ฑํ์ง ์์๋ ๋๋ค(์ธ์คํด์ค ์ฌ์ฌ์ฉ).
class Color {
final String name;
final int code;
// ํด๋์ค ๋ด๋ถ์์๋ง ์ฌ์ฉํ ์ ์๋ ๋น๊ณต๊ฐ(private) ์์ฑ์
Color._internal(this.name, this.code);
// ๋ฏธ๋ฆฌ ์ ์๋ ์์๋ค์ ์ ์ฅํ๋ ์ ์ (static) ๋งต
static final Map<String, Color> _cache = {
'red': Color._internal('red', 0xFF0000),
'green': Color._internal('green', 0x00FF00),
'blue': Color._internal('blue', 0x0000FF),
};
// ํฉํ ๋ฆฌ(factory) ์์ฑ์
factory Color(String name) {
// ์บ์์ ์์ผ๋ฉด ํด๋น ์ธ์คํด์ค ๋ฐํ, ์์ผ๋ฉด ๊ธฐ๋ณธ ์์(๊ฒ์ )์ผ๋ก ์ ์ธ์คํด์ค ์์ฑ
return _cache[name] ?? Color._internal(name, 0x000000);
}
}
void main() {
var red1 = Color('red');
var red2 = Color('red');
var custom = Color('custom');
print(identical(red1, red2)); // true (๊ฐ์ ์ธ์คํด์ค)
print(red1.code); // 16711680 (0xFF0000)
print(custom.code); // 0 (0x000000)
}
์บ์ฑ, ์ฑ๊ธํค, ์กฐ๊ฑด๋ถ ๊ฐ์ฒด ์์ฑ ๋ฑ ๋ค์ํ ์ํฉ์์ ํฉํ ๋ฆฌ ์์ฑ์๋ฅผ ํ์ฉํ ์ ์๋ค.
Methods
Dart, JavaScript์์ ๋ฉ์๋๋ ๊ฐ์ฒด์ ๋์์ ์ ๊ณตํ๋ ํจ์๋ค.
class Example {
// ๋ฉ์๋
doSomething() {
// ...๊ตฌํ
}
}
class Example {
// ๋ฉ์๋
void doSomething() {
// ...๊ตฌํ
}
}
Extending classes
Dart์์ ์๋ฐ์คํฌ๋ฆฝํธ์ ์ ์ฌํ ๋ฐฉ์์ผ๋ก ํด๋์ค๋ฅผ ํ์ฅํ ์ ์๋ค. ๋ถ๋ชจ ํด๋์ค์ ๋ฉ์๋๋ฅผ ์ฌ์ ์(์ค๋ฒ๋ผ์ด๋) ํ ๋ @override
์ด๋
ธํ
์ด์
์ ์ฌ์ฉํ๋ค.
class Animal {
int eyes;
Animal(this.eyes);
makeNoise() {
print('???');
}
}
class Cat extends Animal {
// ๋ถ๋ชจ ํด๋์ค ์์ฑ์์ 2๋ฅผ ์ ๋ฌํ์ฌ ํธ์ถ (์์ฑ์ ์์)
Cat() : super(2);
// makeNoise ๋ฉ์๋ ์ค๋ฒ๋ผ์ด๋
@override
makeNoise() {
print('Meow');
}
}
void main() {
final cat = Cat();
print(cat.eyes); // 2
cat.makeNoise(); // Meow
}
๋ฉ์๋๋ฅผ ์ค๋ฒ๋ผ์ด๋ ํ์ด๋ super
ํค์๋๋ฅผ ์ฌ์ฉํด์ ์์ ๋ฉ์๋๋ฅผ ํธ์ถํ ์ ์๋ค.
class Cat extends Animal {
// ๋ถ๋ชจ ํด๋์ค ์์ฑ์์ 2๋ฅผ ์ ๋ฌํ์ฌ ํธ์ถ (์์ฑ์ ์์)
Cat() : super(2);
// makeNoise ๋ฉ์๋ ์ค๋ฒ๋ผ์ด๋
@override
makeNoise() {
print('Meow');
super.makeNoise();
}
}
void main() {
final cat = Cat();
cat.makeNoise(); // Meow, ???
}
Classes as interfaces
Dart์์ ๋ณ๋์ interface
ํค์๋๊ฐ ์๊ณ , ํด๋์ค ์ ์ ์์ฒด๊ฐ ์ธํฐํ์ด์ค ์ญํ ์ ์ํํ๋ค. ๋ค๋ฅธ ํด๋์ค์ ์ธํฐํ์ด์ค๋ฅผ ๊ตฌํํ ๋ implements
ํค์๋๋ฅผ ์ฌ์ฉํ๋ค. ์๋ฅผ๋ค์ด ํด๋์ค B๊ฐ implements A
๋ฅผ ์ ์ธํ๋ฉด, ํด๋์ค B๋ ํด๋์ค A์ ๋ชจ๋ ๊ณต๊ฐ(public) ๋ฉ์๋์ ์์ฑ์ ๊ตฌํํด์ผ ํ๋ค. extends
ํ์ฅ๊ณผ ๋ฌ๋ฆฌ ๋ฉ์๋์ ํ๋ ๊ตฌํ์ ์ ํด๋์ค์ ๊ณต์ ๋์ง ์๋๋ค.
class Consumer {
consume() {
print('Eating food...');
}
}
class Cat implements Consumer {
@override
consume() {
print('Eating mice...');
}
}
void main() {
Consumer consumer = Cat();
consumer.consume(); // Eating mice...
}
์ธํฐํ์ด์ค๋ก ์ฌ์ฉ๋๋ ํด๋์ค์ ์์ฑ์๋ ์ด๋ฅผ ๊ตฌํํ๋ ํด๋์ค์ ์์๋์ง ์๋๋ค. ๋ฐ๋ผ์ super
๋ฉ์๋๋ฅผ ์ฌ์ฉํ์ฌ ์ธํฐํ์ด์ค์ ๋ฉ์๋๋ฅผ ํธ์ถํ ์ ์๋ค.
class Cat implements Consumer {
@override
consume() {
print('Eating mice...');
super.consume();
// Invalid. The superclass `Object` has no `consume` method.
}
}
์ฌ๋ฌ ์ธํฐํ์ด์ค๋ฅผ ๋์์ ๊ตฌํํ ์๋ ์๋ค. ์ด๋ฅผ ๋ค์ค ์ธํฐํ์ด์ค ๊ตฌํ์ด๋ผ๊ณ ๋ถ๋ฅธ๋ค.
class MyClass implements Interface1, Interface2, Interface3 {
// ์ฌ๋ฌ ์ธํฐํ์ด์ค์ ๋ฉ์๋์ ์์ฑ ๋ชจ๋ ๊ตฌํ
}
Abstract classes and methods
ํด๋์ค์ ํ์ฅ(์์), ์ธํฐํ์ด์ค ๊ตฌํ์ ๊ฐ๋ฅํ์ง๋ง ์ธ์คํด์ค ์์ฑ์ ํ์ฉํ์ง ์์ผ๋ ค๋ฉด ํด๋น ํด๋์ค๋ฅผ abstract
๋ก ํ๊ธฐํ๋ค. ์ถ์ ํด๋์ค๋ ์ผ๋ฐ์ ์ผ๋ก ํ๋ ์ด์์ ์ถ์ ๋ฉ์๋(๊ตฌํ์ด ์๋ ๋ฉ์๋)๋ฅผ ํฌํจํ๊ณ , ์ด ๋ฉ์๋๋ค์ ํ์ ํด๋์ค์์ ๋ฐ๋์ ๊ตฌํ๋ผ์ผ ํ๋ค. ๋ฉ์๋ ๋ณธ๋ฌธ ์์ด ์ ์ธ๋ง ์๋ค๋ฉด ์ถ์ ๋ฉ์๋๋ก ๊ฐ์ฃผ๋๋ค.
abstract class Consumer {
consume();
}
// ์ ์ฒด ํด๋์ค ํ์ฅ
class Dog extends Consumer {
consume() {
print('Eating cookies...');
}
}
// ์ธํฐํ์ด์ค๋ง ๊ตฌํ
class Cat implements Consumer {
consume() {
print('Eating mice...');
}
}
์ถ์ ํด๋์ค๋ ์ผ๋ฐ ๋ฉ์๋๋ ํฌํจํ ์ ์๋ค.
abstract class Shape {
// ์ถ์ ๋ฉ์๋
double area();
// ์ผ๋ฐ ๋ฉ์๋
void printName() {
print("This is a shape");
}
}
class Circle extends Shape {
double radius;
Circle(this.radius);
@override
double area() {
return 3.14 * radius * radius;
}
}
void main() {
var circle = Circle(5);
circle.printName(); // This is a shape
}
Mixins
๋ฏน์ค์ธ์ ํด๋์ค ๊ฐ์ ๊ธฐ๋ฅ์ ๊ณต์ ํ ๋ ์ฌ์ฉํ๋ ๊ฐ๋ ์ผ๋ก, ํน์ ํด๋์ค์ ์ผ๋ถ์ธ ๊ฒ์ฒ๋ผ ํ๋์ ๋ฉ์๋๋ฅผ ํ์ฉํ ์ ์๋๋ก ํด์ค๋ค. ์ด๋ฅผ ํตํด ํ ํด๋์ค์์ ์ฌ๋ฌ ๋ฏน์ค์ธ์ ๊ฒฐํฉํ์ฌ ์ฌ์ฉํ ์ ์๋ค.
๋ฏน์ค์ธ์ ํด๋์ค๋ฅผ ์์ํ๊ฑฐ๋ ๊ณตํต ์กฐ์์ ๊ณต์ ํ์ง ์๋๋ผ๋ ๋์ผํ ๊ธฐ๋ฅ์ ์ฌ๋ฌ ํด๋์ค์์ ๊ณต์ ํ ์ ์๋ ์ ์ฐํ ๋ฐฉ๋ฒ์ ์ ๊ณตํ๋ค. Dart์์ ๋ฏน์ค์ธ์ with
ํค์๋๋ฅผ ์ฌ์ฉํ์ฌ ์ ์ฉํ๋ค. ์ฌ๋ฌ ๋ฏน์ค์ธ์ ์ฌ์ฉํ ๊ฒฝ์ฐ ์ผํ(,)๋ก ๊ตฌ๋ถํ์ฌ ๋์ดํ ์ ์๋ค.
์๋ฐ์คํฌ๋ฆฝํธ์ Dart์ with
๊ฐ์ ํค์๋๊ฐ ์๊ธฐ ๋๋ฌธ์ Object.assign
์ ์ฌ์ฉํ์ฌ ๊ธฐ์กด ๊ฐ์ฒด์ ๋ค๋ฅธ ๊ฐ์ฒด์ ์์ฑ์ ๋ณํฉํ๋ ๋ฐฉ์์ผ๋ก ๊ตฌํํด์ผ ํ๋ค.
// Animal ํด๋์ค ์ ์
class Animal {}
// ๊ธฐ๋ฅ(Mixins) ์ ์
class Flyer {
fly = () => console.log("Flaps wings");
}
class Walker {
walk = () => console.log("Walks on legs");
}
// Animal ํด๋์ค๋ฅผ ์์๋ฐ๋ ํด๋์ค ์ ์
class Bat extends Animal {}
class Goose extends Animal {}
class Dog extends Animal {}
// ํด๋์ค ์ธ์คํด์ค์ ์ฌ๋ฐ๋ฅธ ๊ธฐ๋ฅ์ ํผํฉํ์ฌ ์์ฑ
const bat = Object.assign(
new Bat(), // Bat ์ธ์คํด์ค๋ฅผ ์์ฑํ๊ณ
new Flyer() // Flyer ๊ธฐ๋ฅ ํผํฉ
);
const goose = Object.assign(
new Goose(), // Goose ์ธ์คํด์ค๋ฅผ ์์ฑํ๊ณ
new Flyer(), // Flyer ๊ธฐ๋ฅ ํผํฉ
new Walker() // Walker ๊ธฐ๋ฅ ํผํฉ
);
const dog = Object.assign(
new Dog(), // Dog ์ธ์คํด์ค๋ฅผ ์์ฑํ๊ณ
new Walker() // Walker ๊ธฐ๋ฅ ํผํฉ
);
// ์ฌ๋ฐ๋ฅธ ๋ฉ์๋ ํธ์ถ
bat.fly();
goose.fly();
goose.walk();
dog.walk();
// ์๋ชป๋ ๋ฉ์๋ ํธ์ถ
bat.walk(); // bat ์ธ์คํด์ค์๋ walk ๋ฉ์๋ ์์
dog.fly(); // dog ์ธ์คํด์ค์๋ fly ๋ฉ์๋ ์์
// Animal ์ถ์ ํด๋์ค ์ ์
abstract class Animal {}
// ๊ธฐ๋ฅ(Mixins) ์ ์
class Flyer {
fly() => print('Flaps wings');
}
class Walker {
walk() => print('Walks on legs');
}
// Bat ํด๋์ค ์ ์ - Flyer ๋ฏน์ค์ธ ์ฌ์ฉ
class Bat extends Animal with Flyer {}
// Goose ํด๋์ค ์ ์ - Flyer์ Walker ๋ฏน์ค์ธ ๋ชจ๋ ์ฌ์ฉ
class Goose extends Animal with Flyer, Walker {}
// Dog ํด๋์ค ์ ์ - Walker ๋ฏน์ค์ธ ์ฌ์ฉ
class Dog extends Animal with Walker {}
void main() {
// ์ฌ๋ฐ๋ฅธ ๋ฉ์๋ ํธ์ถ
Bat().fly();
Goose().fly();
Goose().walk();
Dog().walk();
// ์๋ชป๋ ๋ฉ์๋ ํธ์ถ
Bat().walk(); // Walker ๋ฏน์ค์ธ์ ์ฌ์ฉํ์ง ์์์ walk ๋ฉ์๋ ์์
Dog().fly(); // Flyer ๋ฏน์ค์ธ์ ์ฌ์ฉํ์ง ์์์ fly ๋ฉ์๋ ์์
}
๋ฏน์ค์ธ์ด ์ผ๋ฐ ํด๋์ค๋ก ์ฌ์ฉ๋๋ ๊ฒ์ ๋ฐฉ์งํ๋ ค๋ฉด class
๋์ mixin
ํค์๋๋ฅผ ์ฌ์ฉํ๋ค. mixin
ํด๋์ค๋ ์ธ์คํด์ค๋ฅผ ์์ฑํ ์ ์๋ค.
mixin Walker {
walk() => print('Walks legs');
}
// Walker๋ ํด๋์ค๊ฐ ์๋๊ธฐ ๋๋ฌธ์ ์์ ๋ถ๊ฐ
class Bat extends Walker {}
์ฌ๋ฌ ๋ฏน์ค์ธ์ ์ฌ์ฉํ๋ฉด ์๋ก ๊ฒน์น๋ ๋ฉ์๋๋ ํ๋๋ฅผ ๊ฐ์ง ์ ์๋ค. ์ด๋ โถ์์ฒด ํด๋์ค, โท๋ฏน์ค์ธ(์ค๋ฅธ์ชฝ์์ ์ผ์ชฝ์ผ๋ก) โธ๋ถ๋ชจ ํด๋์ค ์์๋ก ๊ตฌํ์ ํ์ํ๋ค.
abstract class Animal {}
mixin Consumer {
eat() => print('Consumer Eating...');
}
mixin Flyer {
eat() => print('Flyer Eating...');
fly() => print('Flying...');
}
// Bird(์์ฒด ํด๋์ค) -> (Flyer -> Consumer) -> Animal(๋ถ๋ชจ ํด๋์ค) ์์๋ก ๊ฒ์ฌ
class Bird extends Animal with Consumer, Flyer {
chirp() => print('Chirping...');
}
void main() {
Bird bird = Bird();
bird.eat(); // Flyer Eating...
bird.chirp(); // Chirping...
bird.fly(); // Flying...
}
Extension
ํ์ฅ ๋ฉ์๋๋ ๊ธฐ์กด ํด๋์ค๋ ์ธํฐํ์ด์ค์ ์๋ก์ด ๋ฉ์๋๋ฅผ ์ถ๊ฐํ ์ ์๋ ๊ธฐ๋ฅ์ด๋ค. ์ด๋ฅผ ํตํด ํด๋์ค์ ์๋ ๊ตฌํ์ ๋ณ๊ฒฝํ์ง ์๊ณ ๋ ๊ธฐ๋ฅ์ ํ์ฅํ ์ ์๋ค. ๋ค๋ฅธ ๋ผ์ด๋ธ๋ฌ๋ฆฌ, Dart SDK ๋ฑ์ ํด๋์ค๋ฅผ ํ์ฅํ ๋ ์ ์ฉํ๊ฒ ์ฐ์ธ๋ค.
// ํ์ฅ ์ด๋ฆ(NumberParsing)์ ์์๋ก ์ง์ ํ ์ ์๋ค.
extension NumberParsing on String {
// String ํ์
์ parseInt ํ์ฅ ๋ฉ์๋ ์ ์
int parseInt() {
// ์ฌ๊ธฐ์ this๋ ํ์ฅ ๋ฉ์๋๋ฅผ ํธ์ถํ String ๊ฐ
return int.parse(this);
}
}
void main() {
print('123'.parseInt()); // 123
}
ํ์ฅ ๋ฉ์๋๋ ์ ์ ํ์
์ ์์กดํ๋ค. dynamic
ํ์
๋ณ์์์ ํ์ฅ ๋ฉ์๋๋ฅผ ์ฌ์ฉํ ์ ์๋ค.
// ...ํ์ฅ ๋ฉ์๋ ์๋ต
void main() {
dynamic num = '2';
print(num.parseInt()); // NoSuchMethodError ๋ฐํ์ ์ค๋ฅ
}
ํ์ฅ ๋ฉ์๋๊ฐ ๋ค๋ฅธ ํ์ผ์ ์ ์๋์ด ์๋ค๋ฉด ํ์ฌ ํ์ผ์์ import ํด์ผ๋ง ์ฌ์ฉํ ์ ์๋ค.
// ํ์ฅ ๋ฉ์๋๊ฐ ์ ์๋์ด ์๋ ํ์ผ import
import 'string_apis.dart';
// ํ์ฅ ๋ฉ์๋ ์ฌ์ฉ
var age = '42'.parseInt();
Getters and setters
Dart์ Getter/Setter๋ ๊ธฐ๋ณธ์ ์ผ๋ก ์๋ฐ์คํฌ๋ฆฝํธ์ ๋์ผํ๊ฒ ์๋ํ๋ค.
// JavaScript
class Person {
_age = 0;
get age() {
return this._age;
}
set age(value) {
if (value < 0) {
throw new Error("Age cannot be negative.");
}
this._age = value;
}
}
var person = new Person();
person.age = 10;
console.log(person.age); // 10
// Dart
class Person {
// ์ธ๋์ค์ฝ์ด(_)๋ก ์์ํ๋ ์ด๋ฆ์ private ํ๋๊ฐ ๋จ
// private ํ๋๋ ์ ์ธ๋ ๋ผ์ด๋ธ๋ฌ๋ฆฌ(ํ์ผ) ์ธ๋ถ์์ ์ ๊ทผ ๋ถ๊ฐ
int _age = 0;
// (ํ๋ผ๋ฏธํฐ๋ฅผ ์๋ตํ ์ถ์ฝํ) int get age => _age;
int get age {
return _age;
}
set age(int value) {
if (value < 0) {
throw ArgumentError('Age cannot be negative.');
}
_age = value;
}
}
void main() {
Person person = Person();
person.age = 10;
print(person.age); // 10
}
์ฐธ๊ณ ๋ก Dart์์ ํด๋์ค ๋ฉค๋ฒ์ ์ ๊ทผํ ๋ this๋ฅผ ์๋ตํ ์ ์๋ค.
Public and private members
์๋ฐ์คํฌ๋ฆฝํธ์ Dart ๋ชจ๋ ์ ๊ทผ ์ ์ด๋ฅผ ์ํ ํค์๋(public, private, protected ๋ฑ)๊ฐ ์๋ค. ๋ชจ๋ ํด๋์ค ๋ฉค๋ฒ๋ ๊ธฐ๋ณธ์ ์ผ๋ก public ์ด๋ค. ์๋ฐ์คํฌ๋ฆฝํธ์ private ๋ฉค๋ฒ ์ ์๋ ํด์(#
)๋ฅผ ์ฌ์ฉํ๊ณ , Dart์์ ์ธ๋์ค์ฝ์ด(_
)๋ฅผ ์ฌ์ฉํ๋ค.
// JavaScript
class Animal {
eyes; // Public field
#paws; // Private field
// Private method
#printEyes() {
print(this.eyes);
}
// Public method
printPaws() {
print(this.#paws);
}
}
// Dart
class Animal {
int eyes; // Public field
int _paws; // Private field
// Private method
void _printEyes() {
print(this.eyes);
}
// Public method
void printPaws() {
print(this._paws);
}
}
์๋ฐ์คํฌ๋ฆฝํธ์ private ํ๋๋ ํด๋์ค ์ธ๋ถ์์ ์ ๊ทผํ ์ ์๊ณ , Dart์ private ํ๋๋ ํ์ผ ์ค์ฝํ ๊ธฐ๋ฐ์ผ๋ก, ๋ค๋ฅธ ํ์ผ(๋ผ์ด๋ธ๋ฌ๋ฆฌ)์์ ์ ๊ทผํ ์ ์๋ค. ๋ผ์ด๋ธ๋ฌ๋ฆฌ์ ์ ๊ทผ ๋ฒ์๋ฅผ ์ฌ๋ฌ ํ์ผ๋ก ํ์ฅํ๋ ค๋ฉด part
์ง์๋ฌธ์ ์ถ๊ฐํ๋ค.
Late variables
ํด๋์ค ํ๋๋ฅผ ๋์ค์ ์ด๊ธฐํ ํด์ผํ ๋ late
ํค์๋๋ฅผ ์ฌ์ฉํ๋ค. ์ด ํค์๋๋ฅผ ์ฌ์ฉํ๋ฉด ํ๋๋ฅผ ์ ์ธํ ๋ ๊ฐ์ ์ฆ์ ํ ๋นํ์ง ์๊ณ ํ์ํ ์์ ์ ์ด๊ธฐํํ ์ ์๋ค. late
ํค์๋๋ฅผ ์ฌ์ฉํ๋ฉด ํด๋น ํ๋๋ non-nullable์ด ๋๋ค. ์ฆ, ํ๋๋ฅผ ์ด๊ธฐํํ๊ธฐ ์ ๊น์ง๋ ์ ๊ทผํ ์ ์๊ณ , ์ด๊ธฐํ ํ์๋ null์ด ๋ ์ ์๋ค.
nullable ํ๋๋ null ๊ฐ์ ๊ฐ์ง ์ ์๊ธฐ ๋๋ฌธ์ ์ด๊ธฐํํ์ง ์์๋ null๋ก ์ ๊ทผํ ์ ์๋ค. ๋ฐ๋ฉด, late
ํค์๋๋ฅผ ์ฌ์ฉํ non-nullable ํค์๋๋ null์ด ๋ ์์๊ณ ์ด๊ธฐํํ์ง ์์ ์ํ์์ ์ ๊ทผํ๋ฉด ๋ฐํ์ ์ค๋ฅ๊ฐ ๋ฐ์ํ๋ค.
class Example {
late String name; // late ํค์๋๋ฅผ ์ฌ์ฉํ์ฌ ๋์ค์ ์ด๊ธฐํ
void initializeName(String newName) {
name = newName; // ํ์ํ ๋ ์ด๊ธฐํ
}
}
void main() {
var example = Example();
example.initializeName('Dart'); // name ์ด๊ธฐํ
print(example.name); // Dart
}
์๋์ฒ๋ผ ์ํ ์ฐธ์กฐ๋ก ์ด๊ธฐํ๋ฅผ ๋ฆ์ถฐ์ผ ํ๋ ๊ฒฝ์ฐ์ late
ํค์๋๋ฅผ ํ์ฉํ ์ ์๋ค.
class PetOwner {
final String name; // ์ฃผ์ธ ์ด๋ฆ (์์ ๋ถ๊ฐ)
late final Pet _pet; // ๋์ค์ ์ด๊ธฐํ๋๋ pet ๊ฐ์ฒด
// Pet ๊ฐ์ฒด๋ PetOwner ๊ฐ์ฒด๋ฅผ ์์ฑ์ ํ๋ผ๋ฏธํฐ๋ก ๋ฐ๊ธฐ ๋๋ฌธ์
// PetOwner ๊ฐ์ฒด๋ฅผ ๋จผ์ ์์ฑํ ๋ค์ Pet ๊ฐ์ฒด๋ฅผ ์ด๊ธฐํ ํด์ผํจ
PetOwner(this.name, String petName) {
_pet = Pet(petName, this);
}
// Pet ๊ฐ์ฒด์ ์ ๊ทผํ๊ธฐ ์ํ Getter
Pet get pet => _pet;
}
class Pet {
final String name; // Pet ์ด๋ฆ
final PetOwner owner; // Pet ์ฃผ์ธ
// ์์ฑ์์์ PetOwner๋ฅผ ๋ฐ์ ์ด๊ธฐํ
Pet(this.name, this.owner);
}
void main() {
PetOwner owner = PetOwner('Bob', 'Fluffy');
print(owner.pet.name); // Fluffy
}
์ปดํ์ผ๋ฌ๊ฐ ๋ณ์์ ์ด๊ธฐํ ์ฌ๋ถ๋ฅผ ํ๋จํ ์ ์๋ ์ํฉ์์ ์ง์ญ ๋ณ์์ late
ํค์๋๋ฅผ ์ฌ์ฉํ๋ค. Dart์์ ๋ณ์๋ฅผ ์ฌ์ฉํ๊ธฐ ์ ์ ๋ฐ๋์ ์ด๊ธฐํํด์ผ ํ๋ค. ํ์ง๋ง ํน์ ์กฐ๊ฑด์ ๋ฐ๋ผ ๋ณ์๊ฐ ์ด๊ธฐํ๋๋ ์ํฉ์์ ์ปดํ์ผ๋ฌ๊ฐ ์ด๊ธฐํ ์ฌ๋ถ๋ฅผ ํ๋จํ์ง ๋ชปํ ์ ์๋ค.
์ด๋ late
ํค์๋๋ฅผ ์ฌ์ฉํ๋ฉด ๋ณ์๋ฅผ ๋์ค์ ์ด๊ธฐํํ๊ฒ ๋ค๊ณ ๋ช
์ํจ์ผ๋ก์จ ์ด๊ธฐํ ์ฒดํฌ๋ฅผ ๋ฐํ์๊น์ง ์ง์ฐ์ํฌ ์ ์๋ค. ์๋ ์์์์ capture
์ธ์์ true
์ฌ๋ถ๋ฅผ ์ปดํ์ผ ์์ ์ ์ ์ ์์ผ๋ฏ๋ก, captures
๋ณ์๋ฅผ late
๋ก ์ ์ธํ์ฌ ๋ฐํ์์์๋ง ์ด๊ธฐํ ์ฒดํฌ๋ฅผ ์ํํ๊ฒ ํ๋ค.
doSomething(int n, bool capture) {
late List<Foo> captures;
if (capture) captures = [];
for (var i = 0; i < n; i++) {
var foo = something(i);
if (capture) captures.add(foo);
}
}
Generics
์๋ฐ์คํฌ๋ฆฝํธ๋ ์ ๋ค๋ฆญ์ ์ ๊ณตํ์ง ์์ง๋ง, Dart๋ ํ์ ์์ ์ฑ์ ๊ฐ์ ํ๊ณ ์ฝ๋ ์ค๋ณต์ ์ค์ด๊ธฐ ์ํ ๋ชฉ์ ์ผ๋ก ์ ๋ค๋ฆญ์ ์ ๊ณตํ๋ค(ํ์ ์คํฌ๋ฆฝํธ์ ์ ๋ค๋ฆญ๊ณผ ์ ์ฌํ ๊ธฐ๋ฅ ์ํ).
Generic methods
์ ๋ค๋ฆญ ํ์
ํ๋ผ๋ฏธํฐ๋ฅผ ์ ์ํ๋ ค๋ฉด ๋ฉ์๋ ์ด๋ฆ ๋ค์ <T>
ํํ๋ก ๋ช
์ํ๋ค. ์ ์ํ ์ ๋ค๋ฆญ ํ์
์ ๋ฉ์๋์ ๋ฐํ ํ์
์ด๋ ๋งค๊ฐ๋ณ์๋ก ์ฌ์ฉํ ์ ์๋ค.
// Key/Value ๋ชจ๋ Object? ํ์
์ ๊ฐ์ง๋ Map
Map<Object?, Object?> _cache = {};
// ๋ฐํ ํ์
, ๋งค๊ฐ๋ณ์๊ฐ ๋ชจ๋ T ์ ๋ค๋ฆญ ํ์
์ ๊ฐ์ง๋ ํจ์
// ๊ฐ์ฅ ์ ๋ถ๋ถ์ ๋ฐํ ํ์
T cache<T>(T value) => (_cache[value] ??= value) as T;
์ผํ(,)๋ก ๊ตฌ๋ถํ์ฌ ์ฌ๋ฌ ์ ๋ค๋ฆญ ํ์ ์ ์ ์ํ ์ ์๋ค.
// ๋ค์ค ์ ๋ค๋ฆญ ์ ์
T transform<T, Q>(T param1, Q param2) { ... }
// ๋ช
์์ ์ผ๋ก ์ ์๋ ํ์
์ผ๋ก ๋ฉ์๋ ํธ์ถ
transform<int, String>(5, 'string value');
// ํ์
์ ์ถ๋ก ํ ์ ์์ ๋ ์๋ตํ ์ ์๋ค
transform(5, 'string value');
Generic classes
์ ๋ค๋ฆญ์ ํด๋์ค์ ์ ์ฉํ์ฌ ํน์ ํ์ ์ ๋ง์ถ ํด๋์ค๋ฅผ ์ฌ์ฌ์ฉํ ์ ์๋ค.
class Cache<T> {
final Map<String, T> _cache = {};
// _cache[key] ๊ฐ์ด ์์์๋ ์๊ธฐ ๋๋ฌธ์ T๋ nullable ์ด์ด์ผ ํ๋ค.
T? getByKey(String key) => _cache[key];
void setByKey(String key, T value) => _cache[key] = value;
}
void main() {
final stringCache = Cache<String>();
stringCache.setByKey('Foo', 'Bar'); // string value๋ ์ ๋ค๋ฆญ๊ณผ ๋งค์นญ๋๋ฏ๋ก Valid
// stringCache.setByKey('Baz', 5); // int ํ์
๊ณผ ์ ๋ค๋ฆญ์ด ๋งค์นญ๋์ง ์์์ Invalid (์ฃผ์ ์ฒ๋ฆฌ)
}
๋ง์ฝ ์ ๋ค๋ฆญ ํ์
์ ๋ช
์ํ์ง ์์ผ๋ฉด ๋ฐํ์ ํ์
์ด Cache<dynamic>
์ด ๋๊ณ , setByKey
๋ฉ์๋์ ๋ ๋ฒ์งธ ์ธ์(T)๋ ๋ชจ๋ ํ์
์ ๋ฐ์ ์ ์๊ฒ ๋๋ค.
Restricting generics
์ ๋ค๋ฆญ์ ์ฌ์ฉํ ๋ extends
ํค์๋๋ฅผ ์ฌ์ฉํด์ ํน์ ํ์
์ผ๋ก ์ ํํ ์ ์๋ค. ์๋ฅผ๋ค์ด T extends num
์ T
๊ฐ num
ํ์
์ด๊ฑฐ๋ num
์ ์๋ธํ์
์ด์ด์ผ ํ๋ค.
class NumberManager<T extends num> {}
void main() {
// int, double๋ ๋ชจ๋ num์ด ์๋ธํ์
์ด๋ฏ๋ก OK
var managerInt = NumberManager<int>();
var managerDouble = NumberManager<double>();
// var managerString = NumberManager<String>(); // Invalid (์ฃผ์ ์ฒ๋ฆฌ)
}
Generics in literals
Map, Set, List ๋ฆฌํฐ๋ด์ ํ์ ์ธ์(arguments)๋ฅผ ๋ฐ์ ์ ์๋ค. Dart๊ฐ ํ์ ์ ์ถ๋ก ํ์ง ๋ชปํ๊ฑฐ๋ ์๋ชป ์ถ๋ก ํ ๋ ์ด ๊ธฐ๋ฅ์ ํ์ฉํ ์ ์๋ค.
// ์๋ ํ์
์ถ๋ก
var objList = [5, 2.0]; // List<num>
// ๋ช
์์ ํ์
์ ์
var objList = <Object>[5, 2.0]; // List<Object>
// ๋ช
์์ ํ์
์ ์
var objSet = <Object>{5, 2.0}; // Set<Object>
Map ๋ฆฌํฐ๋ด์์ ํค์ ๊ฐ์ ๋ํ ํ์ ์ ๋ช ์์ ์ผ๋ก ์ง์ ํ ์ ์๋ค.
// ์๋ ํ์
์ถ๋ก
var map = {'foo': 'bar'}; // Type: Map<String, String>
// ๋ช
์์ ํ์
์ ์
var map = <String, Object>{'foo': 'bar'}; // Type: Map<String, Object>
Doc comments
์ฑ๊ธ ๋ผ์ธ ์ฃผ์ : // ...
// ์์ ๋์ด ๊ณ์ฐ
double area = 3.14 * 4 * 4;
๋ฉํฐ ๋ผ์ธ ์ฃผ์ : /* ... */
/*
* ๋ฆฌ์คํธ์ ๋ชจ๋ ์์ ์ถ๋ ฅ
* ๋ฆฌ์คํธ๋ 1, 2, 3์ผ๋ก ๊ตฌ์ฑ
*/
var lst = [1, 2, 3];
๋ฌธ์ํ ์ฃผ์ : /// ...
๋๋ /** ... */
/// ์ฃผ์ด์ง ์ซ์๊ฐ ์ง์์ธ์ง ์ฌ๋ถ ํ์ธ
bool isEven(int number) {
return number % 2 == 0;
}
๋ฌธ์ํ ์ฃผ์์ dart doc ๋๊ตฌ๋ฅผ ํตํด ๋ฌธ์ํ ํ์ด์ง๋ฅผ ์์ฑํ ์ ์๋ค. ์ฃผ๋ก API ๋ฌธ์ํ๋ฅผ ์ํด ์ฌ์ฉํ๋ค. ///
์ฃผ์์ ์ฌ๋ฌ ์ค์ ๊ฑธ์ณ ์ฌ์ฉํ๋ฉด ๋ฉํฐ ๋ผ์ธ ์ฃผ์๊ณผ ๋์ผํ ํจ๊ณผ๋ฅผ ๋ผ ์ ์๋ค. ///
์คํ์ผ์ ์ฃผ์์ด ๋ ๊ฐ๊ฒฐํ๊ณ ์ฝ๊ธฐ ์ฝ๊ธฐ ๋๋ฌธ์ Dart ํ์์ ๋ ์ ํธํ๋ค๊ณ ํ๋ค.
๊ธ ์์ ์ฌํญ์ ๋ ธ์ ํ์ด์ง์ ๊ฐ์ฅ ๋น ๋ฅด๊ฒ ๋ฐ์๋ฉ๋๋ค. ๋งํฌ๋ฅผ ์ฐธ๊ณ ํด ์ฃผ์ธ์
'๐ช Programming' ์นดํ ๊ณ ๋ฆฌ์ ๋ค๋ฅธ ๊ธ
๋๊ธ
์ด ๊ธ ๊ณต์ ํ๊ธฐ
-
๊ตฌ๋
ํ๊ธฐ
๊ตฌ๋ ํ๊ธฐ
-
์นด์นด์คํก
์นด์นด์คํก
-
๋ผ์ธ
๋ผ์ธ
-
ํธ์ํฐ
ํธ์ํฐ
-
Facebook
Facebook
-
์นด์นด์ค์คํ ๋ฆฌ
์นด์นด์ค์คํ ๋ฆฌ
-
๋ฐด๋
๋ฐด๋
-
๋ค์ด๋ฒ ๋ธ๋ก๊ทธ
๋ค์ด๋ฒ ๋ธ๋ก๊ทธ
-
Pocket
Pocket
-
Evernote
Evernote
๋ค๋ฅธ ๊ธ
-
๋์ปค(Docker)์ ์ฟ ๋ฒ๋คํฐ์ค(Kubernetes) ๊ธฐ๋ณธ ๊ฐ๋
๋์ปค(Docker)์ ์ฟ ๋ฒ๋คํฐ์ค(Kubernetes) ๊ธฐ๋ณธ ๊ฐ๋
2024.09.17 -
[Flutter] ํ๋ฌํฐ ๊ฐ๋ฐ ํ๊ฒฝ ๊ตฌ์ถ for macOS
[Flutter] ํ๋ฌํฐ ๊ฐ๋ฐ ํ๊ฒฝ ๊ตฌ์ถ for macOS
2024.09.03 -
[Dart] ์๋ฐ์คํฌ๋ฆฝํธ ๊ฐ๋ฐ์์ ๋คํธ ํ์ต - Part 1
[Dart] ์๋ฐ์คํฌ๋ฆฝํธ ๊ฐ๋ฐ์์ ๋คํธ ํ์ต - Part 1
2024.08.21 -
[Algorithm] ํ๋ก๊ทธ๋๋จธ์ค - ํผ๋ก๋ / ๋ฐฑํธ๋ํน์ผ๋ก ๋ชจ๋ ๋ถ๋ถ์งํฉ ์ฐพ๊ธฐ
[Algorithm] ํ๋ก๊ทธ๋๋จธ์ค - ํผ๋ก๋ / ๋ฐฑํธ๋ํน์ผ๋ก ๋ชจ๋ ๋ถ๋ถ์งํฉ ์ฐพ๊ธฐ
2024.07.29