[FLUTTER] DART 언어 기초과정 - 4 / A Tour of the Dart Language

in #dart6 years ago

플러터란 ? 구글에서 개발한 크로스 플랫폼 앱 개발 프레임워크이다. 언어는 구글이 개발한 Dart 를 사용한다. 안드로이드, iOS, Web, Desktop 을 지원하며 구글의 차기 OS Fuchsia의 메인개발환경이 된다고 한다.

출처 : https://www.dartlang.org/guides/language/language-tour

  • 최대한 내용을 줄여 표현했습니다. (너무 길면 이해가 힘들고, 어느정도 수준이 되어야 이해가 되기 때문)
  • 혹시 궁금하시다면 위 링크를 참조 하시면 됩니다.

이전 편

50. 클래스 변수와 메소드

50.1. static(고정된) 변수

  • 정적 변수는 상태값 또는 상수값 표현에 유용합니다.
  • static 변수는 호출 전까지 초기화 되지 않습니다.
  • static 변수의 표현은 lowerCamelCase 형태를 지향합니다. (자바랑은 좀 다르네요 : 대문자 + 언더스코어 )
class Queue {
  static const initialCapacity = 16;
  // ···
}

void main() {
  assert(Queue.initialCapacity == 16);
}

50.2. static(고정된) 메소드

  • static 메소드를 통해 손쉽게 호출 할 수 있습니다.
  • 공통적으로 또는 널리 사용되는 유틸리티 및 기능에 대해서는 정적 방법 대신 최상위(top-level) 기능을 사용하는 것이 좋습니다.

ex) top-level function : main과 동일선상에 함수를 생성해 주면 됨

int plus(a, b){
  return a+b;
}
import 'dart:math';

class Point {
  num x, y;
  Point(this.x, this.y);

  static num distanceBetween(Point a, Point b) {
    var dx = a.x - b.x;
    var dy = a.y - b.y;
    return sqrt(dx * dx + dy * dy);
  }
}

void main() {
  var a = Point(2, 2);
  var b = Point(4, 4);
  var distance = Point.distanceBetween(a, b);
  assert(2.8 < distance && distance < 2.9);
  print(distance);
}

51. Generics(제네릭)

  • List<E> 이런 형태로 표현됨 / 리스트 내부 문자로는 E, T, S, K, V 같은 문자를 사용함.
  • 제네릭 형식을 올바르게 지정하면 코드를 더 잘 생성 할 수 있습니다.
  • 제네릭을 사용하여 코드 중복을 줄일 수 있습니다.

아래와 같이 목록(List)의 타입을 String 으로 지정했기 때문에, 다른 타입 42 라는 숫자를 추가하려면 오류가 발생합니다.

var names = List<String>();
names.addAll(['Seth', 'Kathy', 'Lars']);
names.add(42); // 오류 발생

캐시에서 값을 설정/추출할 때 StringCache 라고 명명하면, 매번 각각의 다양의 타입을 만들때마다 클래스를 만들어야 됩니다.

abstract class StringCache {
  String getByKey(String key);
  void setByKey(String key, String value);
}

하지만 제네릭을 활용하면 다양한 타입을 활용할 수 있습니다. 클래스 생성시 T에 타입을 지정하면 해당 부분이 치환되어 자동으로 적용됩니다.

abstract class Cache<T> {
  T getByKey(String key);
  void setByKey(String key, T value);
}

51.2 사용 예시


// collection 형태
var names = <String>['Seth', 'Kathy', 'Lars'];
var pages = <String, String>{
  'index.html': 'Homepage',
  'robots.txt': 'Hints for web robots',
  'humans.txt': 'We are people, not machines'
};

// 파라미터 타입 생성자 형태
var names = List<String>();
names.addAll(['Seth', 'Kathy', 'Lars']);
var nameSet = Set<String>.from(names);

var views = Map<int, View>();

51.3 파라미터 타입 제한

  • extends 구문과 조합하여 활용
  • T extends SomeBaseClass SomeBaseClass 클래스를 상속받은 형태만 사용가능 함 이라고 지정할 수 있다.
class Foo<T extends SomeBaseClass> {
  // Implementation goes here...
  String toString() => "Instance of 'Foo<$T>'";
}

class Extender extends SomeBaseClass {...}

var extenderFoo = Foo<Extender>(); // 정상
var foo = Foo<Object>(); // 오류 

51.4 generic 메소드 사용방법

여기서 첫 번째 (<T>)의 제네릭 형식 매개 변수를 사용하면 여러 위치에서 형식 인수 T를 사용할 수 있습니다.

  • 함수의 리턴 형식 (T).
  • 파라미터 유형 (List <T>).
  • 지역 변수의 유형 (T tmp).
T first<T>(List<T> ts) {

  // 초기화 작업, 오류점검 등등 수행 
  T tmp = ts[0];

  // 추가적으로 점검할 것 또는 작업 처리 등
  return tmp;
}

52. 라이브러리

가져 오기(import) 및 라이브러리(library) 지시문을 사용하면 모듈 식 공유 가능 코드 형태를 구성할 수 있습니다. 밑줄 _ 로 시작하는 식별자는 라이브러리 내부에서만 볼 수 있으며, 라이브러리는 패키지를 사용하여 배포 할 수 있습니다.

52.1 라이브러리 사용방법

  • dart:html 라이브러리를 사용하려면 아래와 같이 프로그램 최상단에 기술하면 됩니다.
import 'dart:html';
  • dart에서 제공하는 빌트인 라이브러리 같은경우 dart: 를 사용합니다.
  • 패키지(pub tool에서 다운받은 패키지) 또는 파일 시스템 내부 경로에 접근하고자 하는 경우 package: 를 사용 합니다.
  • URI와 같은 형태로 해당 프리픽스 (dart:, package: ) 뒤에 사용하고자 하는 스키마 정보를 넣어주면 됩니다.
import 'package:test/test.dart';

52.2 접두사(prefix) 활용

  • 각 라이브러리에 동일 top-level 함수가 존재하는 경우 as를 활용하여 중복되는 요소에 접근할 수 있도록 도와준다.
import 'package:lib1/lib1.dart';
import 'package:lib2/lib2.dart' as lib2;

// lib1 에서 사용되는 Element
Element element1 = Element();

// lib2 에서 사용되는 Element
lib2.Element element2 = lib2.Element();

52.3 필요한 일부 라이브러리만 가져오기

// foo 만 가져온다
import 'package:lib1/lib1.dart' show foo;

// foo 를 제외한 나머지 모두를 가져온다 
import 'package:lib2/lib2.dart' hide foo;

52.4 느리게 라이브러리 가져오기

  • 앱의 초기 기동 시간을 줄이고자 하는 경우
  • A / B 테스트를 수행하고자 라이브러리 부분 교체 테스트 진행을 하고자 하는 경우
  • 옵션 화면, 다이얼로그 같이 잘 사용하지 않는 화면/기능을 로딩하고자 할 때
// deferred as 를 사용하여 라이브러리를 늦게 읽어들인다
import 'package:greetings/hello.dart' deferred as hello;

// 필요할 때 라이브러리 식별자(hello)를 활용하여 로딩을 수행한다.
Future greet() async {
  await hello.loadLibrary();    // 라이브러리 로딩 될 때까지 대기
  hello.printGreeting();        // 로딩 이후 해당 기능 호출
}

참조사항

  • loadLibrary() 를 여러번 호출하더라도 라이브러리는 1번만 로딩 됩니다.
  • 라이브러리 내부 상수, 내부 타입 등 모든 것들은 라이브러리가 로딩되기 전까지는 사용할 수 없습니다.
  • loadLibrary() 는 Future 를 리턴합니다. ( javascript의 Promise와 비슷한 느낌이라 생각하면 됨 )

52.5 라이브러리 구현방법

아래 내용이 포함되어 있습니다.

  • 라이브러리 소스코드 구성하는 방법
  • export 지시자 사용방법
  • 언제 part 지시자를 사용하나 ?
  • 언제 library 지시자를 사용하나 ?

53. 비동기(async) 지원

다트 라이브러리는 Future 또는 Stream 객체를 반환하는 함수로 가득합니다. 이러한 함수는 비동기식입니다.

시간이 많이 소요되는 연산 (예 : I/O)을 설정 한 후 반환되며, 해당 연산이 완료 될 때까지 기다리지 않고 반환됩니다.

async 및 await 키워드는 비동기 프로그래밍을 지원하므로 동기 코드와 비슷한 비동기 코드를 작성할 수 있습니다.

53.1 Future 처리

  • 비동기 함수는 async 지시자를 넣어 함수 내부에서 await 구문을 사용할 수 있습니다.
  • await : 해당 호출 구문이 완료 될 때까지 대기한 이후 결과를 리턴함.
  • async 함수 내부에서는 await을 여러번 사용해도 무방 합니다.
  • Future 를 리턴하는 경우 해당 기능을 활용할 수 있습니다.(아래 좀 더 설명 예정)
Future checkVersion() async {
  var version = await lookUpVersion();
  // version 정보를 가지고 뭔가를 수행
}

53.2 비동기함수(async function) 선언

// 동기
String lookUpVersion() => '1.0.0';

// 비동기 
Future<String> lookUpVersion() async => '1.0.0';

53.3 스트림 처리(Handling Streams)

    1. (await for) : 스트림에서 값이 도착 할 때까지 대기
    1. 수신한 값(varOrType) 을 가지고 작업 처리
    1. 스트림이 닫힐 때까지 1과 2를 반복합니다.
await for (varOrType identifier in expression) {
  // 해당 스트림에서 값을 보내줄 때(emit) 마다 수행
}

사용 예시

Future main() async {
  // ...
  await for (var request in requestServer) {
    handleRequest(request);
  }
  // ...
}

54. 제너레이터:생성기(Generators)

느리게 값을 열거형으로 생성하는 형태의 경우 생성기함수(Generator function)을 사용하는 것을 고려 해봄직 합니다.

  • 동기 생성기 : 열거형(Iterable) 개체 반환

  • 비동기 생성기 : 스트림(Stream) 개체 반환

  • 몸체(body)에 sync*(비동기)를 마킹하고, yield(양보)를 사용하여 값을 배달 합니다.

Iterable<int> naturalsTo(int n) sync* {
  int k = 0;
  while (k < n) yield k++;
}
  • 몸체(body)에 async*(비동기)를 마킹하고, yield(양보)를 사용하여 값을 배달 합니다.
Stream<int> asynchronousNaturalsTo(int n) async* {
  int k = 0;
  while (k < n) yield k++;
}

순환 형태의 경우 sync*yield*를 사용하여 성능을 향상시킬 수 있습니다.

Iterable<int> naturalsDownFrom(int n) sync* {
  if (n > 0) {
    yield n;
    yield* naturalsDownFrom(n - 1);
  }
}

55. 부를수 있는 클래스(Callable classes)

call 메소드를 사용하여 해당 클래스를 호출(call)할 수 있습니다.

    1. 클래스를 생성
    1. 변수화 한 이후 값을 넣어 호출
class WannabeFunction {
  call(String a, String b, String c) => '$a $b $c!';
}

main() {
  var wf = new WannabeFunction();
  var out = wf("Hi","there,","gang");
  print('$out');
}

56. typedef

Dart에서 함수는 문자열이고 숫자는 객체와 같은 객체입니다. typedef 또는 함수 유형 별명은 함수 유형에 필드 및 리턴 유형을 선언 할 때 사용할 수있는 이름을 제공하며, 함수 유형이 변수에 지정 될 때 유형 정보를 보유합니다.

  • 현재 함수(Function)에 한정적으로 적용되며, 향후 변경될 예정입니다.

57. metadata

메타 데이터를 사용하여 코드에 대한 추가 정보를 제공할 수 있습니다.(메타 데이터의 어노테이션은 문자 @로 시작합니다.)

@deprecated : 사라질 예정 (이전 메소드 사용자에 대한 배려)

class Television {
  /// 사라질 예정(Deprecated) : 대신 turnOn 매소드를 사용 바랍니다.
  @deprecated
  void activate() {
    turnOn();
  }

  /// TV 파워 키기
  void turnOn() {...}
}

@Todo : 할 일

import 'todo.dart';

@Todo('seth', 'make this do something')
void doSomething() {
  print('do something');
}

58. 주석(Comment)

한줄짜리

void main() {
  // TODO: AbstractLlamaGreetingFactory 로 리펙토링 하자 !
  print('Welcome to my Llama farm!');
}

멀티라인 주석

void main() {
  /*
   * 많은 일 을 해야 됨. 닭을 키우는 것을 고려

  Llama larry = Llama();
  larry.feed();
  larry.exercise();
  larry.clean();
   */
}

59. 문서주석 (Document Comments)

  • /// 또는 /**를 사용하여 내용을 기록합니다.
  • [파라미터명] 을 사용하여 해당 함수의 파라미터를 지칭할 수 있습니다.
/// A domesticated South American camelid (Lama glama).
///
/// Andean cultures have used llamas as meat and pack
/// animals since pre-Hispanic times.
class Llama {
  String name;

  /// Feeds your llama [Food].
  ///
  /// The typical llama eats one bale of hay per week.
  void feed(Food food) {
    // ...
  }

  /// Exercises your llama with an [activity] for
  /// [timeLimit] minutes.
  void exercise(Activity activity, int timeLimit) {
    // ...
  }
}

맺음말

4회로 나눠 기초 개발 가이드를 설명 드렸네요 :) 둘러보기식 설명이긴 하지만 프로그램을 첨 하시는 분들께는 정말 이건 뭐지?! 라고 생각할 만큼의 내용이네요 그리고 저 또한 dart에 대해 숙련자가 아닌지라 100%이해하고 요약하기 보단 번역기를 돌린 부분도 상당수 포함되어 있긴합니다. 하지만 중간중간 나오는 예제 소스코드를 따라해 보면서 이곳까지 오셨다면 분명 실력향상과 첨에는 dart가 뭐지 ? 라고 했다가 이젠 어느정도 느낌은 오시지 않았을까 라고 생각해 봅니다.

이후로는 여기서 알려준 기초 설명을 토대로 하나 둘씩 살을 붙여 가면서 반복 학습을 진행하도록 해보겠습니다.

읽기 힘든 글 읽어주셔서 (또는 눈팅 이라도) 감사합니다

관련 글 링크

@flutters : 제가 작성한 글 중 fluter 관련 글만 모아서 리스팀 처리

관련글(영문)

연재글

설치/설정


aaronhong_banner.jpg

Sort:  

좀 공부하려 했다가...ㅋㅋ
스몬게임을 하기로 했습니다.
저에겐 너무 고급 영역
전 행님 만들어 논거 쓰는걸로~~~ ㅎ

:) 그럼 스몬에서 봐용 ㅎㅎ

Posted using Partiko Android

다트하려면 이런 언어를 배워야 하는건가요? ㅠㅠ

딩동댕 ! 정 가운데를 맞추면 됩니다. 그렇다고 가운데님께 던지면 큰일남요 :)

Posted using Partiko Android

Hi @wonsama!

Your post was upvoted by @steem-ua, new Steem dApp, using UserAuthority for algorithmic post curation!
Your UA account score is currently 3.815 which ranks you at #4619 across all Steem accounts.
Your rank has improved 7 places in the last three days (old rank 4626).

In our last Algorithmic Curation Round, consisting of 223 contributions, your post is ranked at #138.

Evaluation of your UA score:
  • You're on the right track, try to gather more followers.
  • The readers like your work!
  • You have already shown user engagement, try to improve it further.

Feel free to join our @steem-ua Discord server