[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
๋๊ธ์ ์ฌ์ฉํ ์ ์์ต๋๋ค.