Flutter2022. 8. 2. 16:27

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)
});

 

 

아주 아주 퀵하게 훓어 보았다.

 

Posted by 삼스