Dart 언어 둘러보기
자세히 알아볼 시간이 없다..
다른 언어 공부할때 처럼 휘리릭 둘러보자. 자세한건 코딩하면서 …
c++ 비슷하면서 kotlin같기도 하고 머 그렇다.
void main() {
print(‘Hello, World!’);
}
타입추론이 적용되고 타입체크가 강력하게 이루어진다.
var name = ‘Voyager I’; // 문자열
var year = 1977; // 숫자
var antennaDiameter = 3.7; // 부동소수
var flybyObjects = [‘Jupiter’, ‘Saturn’, ‘Uranus’, ‘Neptune’]; // 배열
var image = { // 딕셔너리
‘tags’: [‘stern’],
‘url’: ‘//path/to/saturn.jpg’
};
흐름제어
if (year >= 2001) {
print(‘21st century’);
} else if (year >= 1901) {
print(‘20st century’);
}
for (final object in flybyObjects) {
print(object)
}
for (int month=1; month<=12; month++) {
print(month);
}
While (year < 2016) {
year += 1;
}
함수
int fibonacci(int n) {
if (n=0 || n==1) return n;
return fibonacci(n - 1) + fibonacci(n - 2);
}
var result = fibonacci(20);
스트림함수호출을 아래와 같이 할 수 있으며 함수를 인자로 사용할수도 있다. 아래 코드에서 forEach의 print가 함수 인자로 사용된것을 볼수 있다.
flybyObjects.where((name) => name.contains(‘turn’)).forEach(print);
import
// Dart core lib 포함
import ‘daar:math’;
// 외부 패키지 라이브러리 포함
Import ‘package:test/test.dart’;
// 다른 파일 포함
Import ‘path/to/my_other_file.dart’;
클래스
class Spacecraft {
String name;
DateTime? launchDate; // nullable
int? get launchYear => launchDate?.year; // getter
Spacecraft(this.name, this.launchDate) {. // 생성자.
}
Spacecraft.unlaunched(String name) : this(name, null); // 이름을 갖는 생성자.
// 메서드
void describe() {
print(‘Spacecraft: $name’);
var launchDate = this.launchDate;
if (launchDate != null) {
int years = DateTime.now().difference(launchDate).inDays ~/ 365;
print(‘Launched: $launchYear ($years years ago)’);
} else {
print(‘Unlaunched’);
}
}
}
var voyager = Spacecraft(‘Voyager I’, DateTime(1977, 9, 5));
voyager.describe();
var voyager3 = Spacecrafe.unlaunched(‘Voyager III’);
voyager3.describe();
열거자(Enums)
// 일반 열거자
enum PlanetType { terrestrial, gas, ice }
// 고급열거자
enum Planet {
mercury(planetType: PlanetType.terrestrial, moons: 0, hasRings: false),
venus(planetType: PlanetType.terrestrial, moons: 0, hasRings: false),
// …
uranus(planetType: PlanetType.ice, moons, 27, hasRings: true),
neptune(planetType: PlanetType.ice, moons: 14, hasRings: true;
// constant 생성자
const Planet ( { required this.planetType, required this.moons, required this.hasRings } );
final PlanetType planetType;
final int moons;
final bool hasRings;
}
usage
final yourPlanet = Planet.earth;
if (!yourPlanet.hasRings) {
print(‘Your planet doesn’t has Rings’);
}
클래스 상속
class Orbiter extends Spacecraft {
double altitude;
Orbiter(super.name, DateTime super.launchDate, this.altitude);
}
Mixins
다중클래스 구조에서 코드를 재사용하는 방법을 제공한다. C++의 다중상속이 복잡함때문에 다른 언어는 다 삭제 했는데 얘는 왜 있는건지 모르겠다.
mixin Piloted {
int astronauts = 1;
void describeCrew() {
print(‘Number of astronauts: $astronauts’);
}
}
class PilotedCraft extends Spacecraft with Piloted {
…
}
PilotedCraft가 astronauts필드를 갖게 되었고 describeCrew()호출이 가능해졌다.
interface
dart는 interface 키워드가 없으며 모든 클래스는 기본적으로 인터페이스로 간주해도 된다.
class MockSpaceCraft implements Spacecraft {
// …
}
mixin과 implements와 머가 다를까?
일단 implements만으로도 클래스의 다중상속이 가능해진다.
extends로는 다중상속이 안된다. implements와 mixin을 혼용하니 컴파일오류가 난다.
흠 다중상속을 오랫동안 잊고 살았는데 다트에서 부활하니 참 당황스럽네..
왜 이런걸 이런식으로 지원하는지 언어 설계자의 머리속에 들어가보고 싶다.
mixin설계자와 implements설계자가 다른걸까?
abstract 클래스는 그리 헤깔리지 않게 지원한다.
abstract class Describable {
void describe();
void describeWithEmphasis() {
print(‘===========‘);
describe();
print(‘===========‘);
}
}
비동기호출
Future를 제공하여 비동기 호출을 지원한다.
const oneSecond = Duration(seconds: 1);
Future<void> printWithDelay(String message) async {
await Future.delayed(oneSecond);
print(message);
}
위 코드는 다음코드와 동일하다.
Future<void> printWithDelay(String message) {
return Future.delayed(oneSecond).then((_) {
print(message);
});
}
아래 코드를 보면 async, await의 사용이 코드를 얼마나 읽기 쉽게 해주는지 확인할 수 있다.
Future<void> createDescriptions(Iterable<String> objects) async {
for (final object in objects) {
try {
var file = File(‘$object.txt’);
if (await file.exists()) {
var modified = await file.lastModified();
print(‘FIle for $object aleady exists. It was modified on $modified.’);
continue;
}
await file.create();
await file.writeAsString(‘Start describing $object in this file.’);
} on IOException catch (e) {
print(‘Cannot create description for $object : %e’);
}
}
}
async*를 사용하여 더 나이스한 코딩이 가능하다.
Stream<String> report(Spacecraft craft, Iterable<String> objects) async* {
for (final object in objects) {
await Future.delayed(oneSecond);
yield ‘${craft.name} flies by $object’);
}
}
예외
예외가 필요하면 예외를 아래와 같이 발생시킨다.
if (astronauts == 0) {
throw StateError(‘No astronauts.’);
}
try {
for (final object in flybyObjects) {
var description = await File($object.txt).readAsString();
print(description);
}
} on IOException catch (e) {
print(‘Could not describe object: $e’);
} finally {
flybyObjects.clear();
}
함수 파라메터
함수를 인자로 넘길 수 있으며 이를 통해 콜백함수를 사용할 수 있다.
void getResultWithCallback(void onResult(String msg)) async {
await Duration(seconds: 5);
onResult('on result!!!');
}
getResultWithCallback((ret)=> {
print(ret)
});
아주 아주 퀵하게 훓어 보았다.