<?xml version="1.0" encoding="utf-8"?>
<rss version="2.0" xmlns:atom="http://www.w3.org/2005/Atom">
    <channel>
        <title>t0dd-kr</title>
        <link>https://velog.io/</link>
        <description>Javascript로 많은 것을 쉽고 빠르고 재밌게 만드는 것을 좋아합니다.</description>
        <lastBuildDate>Fri, 25 Sep 2020 05:55:48 GMT</lastBuildDate>
        <docs>https://validator.w3.org/feed/docs/rss2.html</docs>
        <generator>https://github.com/jpmonette/feed</generator>
        <image>
            <title>t0dd-kr</title>
            <url>https://images.velog.io/images/t0dd-kr/profile/151cda10-2ab5-4855-96d3-56ce0796ab62/social.png</url>
            <link>https://velog.io/</link>
        </image>
        <copyright>Copyright (C) 2019. t0dd-kr. All rights reserved.</copyright>
        <atom:link href="https://v2.velog.io/rss/t0dd-kr" rel="self" type="application/rss+xml"/>
        <item>
            <title><![CDATA[Dart Language Tour #6]]></title>
            <link>https://velog.io/@t0dd-kr/Dart-Language-Tour-6</link>
            <guid>https://velog.io/@t0dd-kr/Dart-Language-Tour-6</guid>
            <pubDate>Fri, 25 Sep 2020 05:55:48 GMT</pubDate>
            <description><![CDATA[<h2 id="클래스">클래스</h2>
<p>Dart는 클래스와 믹스 인 기반 상속이있는 _객체 지향 언어_입니다. 모든 객체는 클래스의 인스턴스이며 모든 클래스는 _Object_의 자손입니다. Mixin 기반 상속은 모든 클래스 (Object 제외)에 정확히 하나의 수퍼 클래스가 있지만 클래스 본문은 여러 클래스 계층에서 재사용 될 수 있음을 의미합니다. 확장 메서드는 클래스를 변경하거나 하위 클래스를 만들지 않고 클래스에 기능을 추가하는 방법입니다.</p>
<h3 id="클래스-멤버-사용">클래스 멤버 사용</h3>
<p>개체에는 함수와 데이터 (각각 메서드 및 인스턴스 변수)로 구성된 멤버가 있습니다. 메소드를 호출하면 객체에서 호출합니다. 메소드는 해당 객체의 함수와 데이터에 액세스 할 수 있습니다.</p>
<p>인스턴스 변수 또는 메서드를 참조하려면 점(<code>.</code>)을 사용합니다.</p>
<pre><code class="language-dart">var p = Point(2, 2);

// Set the value of the instance variable y.
p.y = 3;

// Get the value of y.
assert(p.y == 3);

// Invoke distanceTo() on p.
double distance = p.distanceTo(Point(4, 4));</code></pre>
<p>왼쪽 피연산자가 <code>null</code> 일 때 예외를 방지하려면 <code>.</code> 대신에 <code>?.</code> 를 사용하세요.</p>
<pre><code class="language-dart">p?.y = 4;</code></pre>
<h3 id="생성자-사용">생성자 사용</h3>
<p>생성자를 사용하여 개체를 만들 수 있습니다. 생성자 이름은 <em>ClassName</em> 또는 <em>ClassName.identifier</em> 일 수 있습니다. 예를 들어 다음 코드는 <code>Point()</code> 및 <code>Point.fromJson()</code> 생성자를 사용하여 <em>Point</em> 객체를 만듭니다.</p>
<pre><code class="language-dart">var p1 = Point(2, 2);
var p2 = Point.fromJson({&#39;x&#39;: 1, &#39;y&#39;: 2});</code></pre>
<p>아래 코드는 동일한 효과가 있지만 생성자 이름 앞에 선택적 <code>new</code> 키워드를 사용합니다.</p>
<pre><code class="language-dart">var p1 = new Point(2, 2);
var p2 = new Point.fromJson({&#39;x&#39;: 1, &#39;y&#39;: 2});</code></pre>
<blockquote>
<p><code>new</code> 키워드는 Dart2 에서 선택 사항이 되었습니다.</p>
</blockquote>
<p>일부 클래스는 _상수 생성자_를 제공합니다. _상수 생성자_를 사용하여 _컴파일 타임 상수_를 만들려면 생성자 이름 앞에 <code>const</code> 키워드를 넣으십시오.</p>
<pre><code class="language-dart">var p = const ImmutablePoint(2, 2);</code></pre>
<p>두 개의 동일한 컴파일 타임 상수를 생성하면 단일 표준 인스턴스가 생성됩니다.</p>
<pre><code class="language-dart">var a = const ImmutablePoint(1, 1);
var b = const ImmutablePoint(1, 1);

assert(identical(a, b)); // 두 객체는 같습니다.</code></pre>
<p>상수 컨텍스트 내에서 생성자 또는 리터럴 앞에 <code>const</code>를 생략 할 수 있습니다. 예를 들어, <em>Map</em> 상수를 만드는 다음 코드를 살펴보십시오.</p>
<pre><code class="language-dart">// const 키워드를 아주 많이 사용합니다.
const pointAndLine = const {
  &#39;point&#39;: const [const ImmutablePoint(0, 0)],
  &#39;line&#39;: const [const ImmutablePoint(1, 10), const ImmutablePoint(-2, 11)],
};</code></pre>
<p><code>const</code> 키워드의 첫 번째 사용을 제외하고 모두 생략 할 수 있습니다.</p>
<pre><code class="language-dart">// const 키워드를 단 한번만 사용하여도 위 코드와 같습니다.
const pointAndLine = {
  &#39;point&#39;: [ImmutablePoint(0, 0)],
  &#39;line&#39;: [ImmutablePoint(1, 10), ImmutablePoint(-2, 11)],
};</code></pre>
<p>상수 생성자가 상수 컨텍스트 외부에 있고 <code>const</code>없이 호출되면 상수가 아닌 객체를 만듭니다.</p>
<pre><code class="language-dart">var a = const ImmutablePoint(1, 1); // 상수 생성
var b = ImmutablePoint(1, 1); // 비 상수 생성

assert(!identical(a, b)); // 같지 않습니다.</code></pre>
<blockquote>
<p><code>const</code> 키워드는 Dart2의 상수 컨텍스트 내에서 선택 사항이되었습니다.</p>
</blockquote>
<h3 id="객체-유형-가져오기">객체 유형 가져오기</h3>
<p>런타임에 객체의 유형을 가져 오려면 <em>Type</em> 객체를 반환하는 _Object_의 <code>runtimeType</code> 속성을 사용할 수 있습니다.</p>
<pre><code class="language-dart">print(&#39;The type of a is ${a.runtimeType}&#39;);</code></pre>
<p>여기까지 클래스 사용 방법을 살펴 보았습니다. 이 섹션의 나머지 부분에서는 클래스를 구현하는 방법을 보여줍니다.</p>
<h3 id="인스턴스-변수">인스턴스 변수</h3>
<p>인스턴스 변수를 선언하는 방법은 다음과 같습니다.</p>
<pre><code class="language-dart">class Point {
  double x; // Declare instance variable x, initially null.
  double y; // Declare y, initially null.
  double z = 0; // Declare z, initially 0.
}</code></pre>
<p>초기화되지 않은 모든 인스턴스 변수의 값은 <code>null</code>입니다.</p>
<p>모든 인스턴스 변수는 암시 적 <code>getter</code> 메서드를 생성합니다. 최종 인스턴스 변수가 아닌 경우에도 암시 적 <code>setter</code> 메서드가 생성됩니다. 자세한 내용은 <a href="https://dart.dev/guides/language/language-tour#getters-and-setters">Getters 및 Setters</a>를 참조하십시오.</p>
<pre><code class="language-dart">class Point {
  double x;
  double y;
}

void main() {
  var point = Point();
  point.x = 4; // Use the setter method for x.
  assert(point.x == 4); // Use the getter method for x.
  assert(point.y == null); // Values default to null.
}</code></pre>
<p>(생성자나 메서드 대신) 선언 된 인스턴스 변수를 초기화하면 인스턴스가 생성될 때 값이 설정되며, 생성자 및 초기화 목록이 실행되기 전입니다.</p>
<h3 id="생성자">생성자</h3>
<p>클래스와 이름이 같은 함수를 생성하여 생성자를 선언합니다 (명시 된 생성자에 설명 된 추가 식별자도 추가 할 수 있음). 생성자의 가장 일반적인 형태인 _일반 생성자_는 클래스의 새 인스턴스를 만듭니다.</p>
<pre><code class="language-dart">class Point {
  double x, y;

  Point(double x, double y) {
    // There&#39;s a better way to do this, stay tuned.
    this.x = x;
    this.y = y;
  }
}</code></pre>
<p><code>this</code> 키워드는 현재 인스턴스를 참조합니다.</p>
<blockquote>
<p><code>this</code>는 이름 충돌이있는 경우에만 사용하십시오. 그렇지 않으면 Dart 스타일은 <code>this</code>를 생략합니다.</p>
</blockquote>
<p>생성자 인수를 인스턴스 변수에 할당하는 패턴은 매우 일반적이므로 Dart에는 이를 쉽게 하기위한 _문법적 설탕_이 있습니다.</p>
<pre><code class="language-dart">class Point {
  double x, y;

  // Syntactic sugar for setting x and y
  // before the constructor body runs.
  Point(this.x, this.y);
}</code></pre>
<h4 id="기본-생성자">기본 생성자</h4>
<p>생성자를 선언하지 않으면 기본 생성자가 제공됩니다. 기본 생성자에는 인수가 없으며 수퍼 클래스에서 인수가없는 생성자를 호출합니다.</p>
<h4 id="상속되지-않는-생성자">상속되지 않는 생성자</h4>
<p>하위 클래스는 수퍼 클래스에서 생성자를 상속하지 않습니다. 생성자를 선언하지 않는 하위 클래스에는 기본 (인수, 이름 없음) 생성자 만 있습니다.</p>
<h4 id="명시된-생성자">명시된 생성자</h4>
<p>명시된 생성자를 사용하여 클래스에 대해 여러 생성자를 구현하거나 추가 명확성을 제공합니다.</p>
<pre><code class="language-dart">class Point {
  double x, y;

  Point(this.x, this.y);

  // Named constructor
  Point.origin() {
    x = 0;
    y = 0;
  }
}</code></pre>
<p>생성자는 상속되지 않습니다. 즉, 수퍼 클래스의 명시된 생성자가 하위 클래스에서 상속되지 않습니다. 슈퍼 클래스에 정의된 명시된 생성자로 서브 클래스를 생성하려면 해당 생성자를 서브 클래스에서 구현해야합니다.</p>
<h4 id="기본이-아닌-슈퍼-클래스-생성자-호출">기본이 아닌 슈퍼 클래스 생성자 호출</h4>
<p>기본적으로 하위 클래스의 생성자는 수퍼 클래스의 명시되지 않은 인수없는 생성자를 호출합니다. 슈퍼 클래스의 생성자는 생성자 본문의 시작 부분에서 호출됩니다. <a href="https://dart.dev/guides/language/language-tour#initializer-list">이니셜라이저 목록</a>도 사용중인 경우 수퍼 클래스가 호출되기 전에 실행됩니다. 요약하면 실행 순서는 다음과 같습니다.</p>
<ol>
<li>이니셜 라이저 목록</li>
<li>슈퍼 클래스의 인수없는 생성자</li>
<li>메인 클래스의 인수없는 생성자</li>
</ol>
<p>수퍼 클래스에 이름이 지정되지 않은 인수없는 생성자가 없으면 수퍼 클래스의 생성자 중 하나를 수동으로 호출해야합니다. 생성자 본문 (있는 경우) 바로 앞에 콜론 (<code>:</code>) 뒤에 수퍼 클래스 생성자를 지정합니다.</p>
<p>다음 예제에서 <em>Employee</em> 클래스의 생성자는 수퍼 클래스 _Person_에 대해 명명 된 생성자를 호출합니다. 실행을 클릭하여 코드를 실행합니다.</p>
<h5 id="코드">코드</h5>
<pre><code class="language-dart">class Person {
  String firstName;

  Person.fromJson(Map data) {
    print(&#39;in Person&#39;);
  }
}

class Employee extends Person {
  // Person does not have a default constructor;
  // you must call super.fromJson(data).
  Employee.fromJson(Map data) : super.fromJson(data) {
    print(&#39;in Employee&#39;);
  }
}

main() {
  var emp = new Employee.fromJson({});

  // Prints:
  // in Person
  // in Employee
  if (emp is Person) {
    // Type check
    emp.firstName = &#39;Bob&#39;;
  }
  (emp as Person).firstName = &#39;Bob&#39;;
}</code></pre>
<h5 id="결과">결과</h5>
<pre><code>in Person
in Employee</code></pre><p>슈퍼 클래스 생성자에 대한 인수는 생성자를 호출하기 전에 평가되기 때문에 인수는 함수 호출과 같은 표현식이 될 수 있습니다.</p>
<pre><code class="language-dart">class Employee extends Person {
  Employee() : super.fromJson(defaultData);
  // ···
}</code></pre>
<blockquote>
<p>슈퍼 클래스 생성자에 대한 인수는 <code>this</code>에 액세스 할 수 없습니다. 예를 들어, 인수는 인스턴스 메서드가 아닌 정적 메서드를 호출 할 수 있습니다.</p>
</blockquote>
<h4 id="이니셜라이저-목록">이니셜라이저 목록</h4>
<p>슈퍼 클래스 생성자를 호출하는 것 외에도 생성자 본문이 실행되기 전에 인스턴스 변수를 초기화 할 수도 있습니다. _이니셜라이저_는 쉼표로 구분하십시오.</p>
<pre><code class="language-dart">// Initializer list sets instance variables before
// the constructor body runs.
Point.fromJson(Map&lt;String, double&gt; json)
    : x = json[&#39;x&#39;],
      y = json[&#39;y&#39;] {
  print(&#39;In Point.fromJson(): ($x, $y)&#39;);
}</code></pre>
<blockquote>
<p>이니셜라이저의 오른쪽에는 <code>this</code>에 대한 액세스 권한이 없습니다.</p>
</blockquote>
<p>개발 중에 이니셜 라이저 목록에서 <code>assert</code>를 사용하여 입력의 유효성을 검사 할 수 있습니다.</p>
<pre><code class="language-dart">Point.withAssert(this.x, this.y) : assert(x &gt;= 0) {
  print(&#39;In Point.withAssert(): ($x, $y)&#39;);
}</code></pre>
<p>이니셜라이저 목록은 최종 필드를 설정할 때 편리합니다. 다음 예제는 이니셜라이저 목록에서 세 개의 마지막 필드를 초기화합니다. 실행을 클릭하여 코드를 실행합니다.</p>
<h5 id="코드-1">코드</h5>
<pre><code class="language-dart">import &#39;dart:math&#39;;

class Point {
  final num x;
  final num y;
  final num distanceFromOrigin;

  Point(x, y)
      : x = x,
        y = y,
        distanceFromOrigin = sqrt(x * x + y * y);
}

main() {
  var p = new Point(2, 3);
  print(p.distanceFromOrigin);
}</code></pre>
<h5 id="결과-1">결과</h5>
<pre><code>3.605551275463989</code></pre><h4 id="생성자-리디렉션">생성자 리디렉션</h4>
<p>때때로 생성자의 유일한 목적은 동일한 클래스의 다른 생성자로 리디렉션하는 것입니다. 리디렉션 생성자의 본문이 비어 있으며 생성자 호출이 콜론 (<code>:</code>) 뒤에 표시됩니다.</p>
<pre><code class="language-dart">class Point {
  double x, y;

  // The main constructor for this class.
  Point(this.x, this.y);

  // Delegates to the main constructor.
  Point.alongXAxis(double x) : this(x, 0);
}</code></pre>
<h4 id="상수-생성자">상수 생성자</h4>
<p>클래스가 변경되지 않는 객체를 생성하는 경우 이러한 객체를 컴파일 시간 상수로 만들 수 있습니다. 이렇게 하려면 상수 생성자를 정의하고 모든 인스턴스 변수가 최종 변수인지 확인해야 합니다.</p>
<pre><code class="language-dart">class ImmutablePoint {
  static final ImmutablePoint origin =
      const ImmutablePoint(0, 0);

  final double x, y;

  const ImmutablePoint(this.x, this.y);
}</code></pre>
<p>상수 생성자가 항상 상수를 만드는 것은 아닙니다. 자세한 내용은 <a href="https://dart.dev/guides/language/language-tour#using-constructors">생성자 사용 섹션</a>을 참조하세요.</p>
<h4 id="팩토리-생성자">팩토리 생성자</h4>
<p>항상 클래스의 새 인스턴스를 만들지는 않는 생성자를 구현할 때 <code>factory</code> 키워드를 사용합니다. 예를 들어 팩토리 생성자는 캐시에서 인스턴스를 반환하거나 하위 유형의 인스턴스를 반환 할 수 있습니다. 팩토리 생성자의 또 다른 사용 사례는 이니셜라이저 목록에서 처리 할 수없는 로직을 사용하여 최종 변수를 초기화하는 것입니다.</p>
<p>다음 예제에서 <code>Logger</code> 팩토리 생성자는 캐시에서 객체를 반환하고 <code>Logger.fromJson</code> 팩토리 생성자는 JSON 객체에서 최종 변수를 초기화합니다.</p>
<pre><code class="language-dart">class Logger {
  final String name;
  bool mute = false;

  // _cache is library-private, thanks to
  // the _ in front of its name.
  static final Map&lt;String, Logger&gt; _cache =
      &lt;String, Logger&gt;{};

  factory Logger(String name) {
    return _cache.putIfAbsent(
        name, () =&gt; Logger._internal(name));
  }

  factory Logger.fromJson(Map&lt;String, Object&gt; json) {
    return Logger(json[&#39;name&#39;].toString());
  }

  Logger._internal(this.name);

  void log(String msg) {
    if (!mute) print(msg);
  }
}</code></pre>
<blockquote>
<p>팩토리 생성자는 <code>this</code>에 액세스 할 수 없습니다.</p>
</blockquote>
<p>다른 생성자와 마찬가지로 팩토리 생성자를 호출합니다.</p>
<pre><code class="language-dart">var logger = Logger(&#39;UI&#39;);
logger.log(&#39;Button clicked&#39;);

var logMap = {&#39;name&#39;: &#39;UI&#39;};
var loggerJson = Logger.fromJson(logMap);</code></pre>
<h3 id="메서드">메서드</h3>
<p>메서드는 개체에 동작을 제공하는 함수입니다.</p>
<h4 id="인스턴스-메서드">인스턴스 메서드</h4>
<p>객체의 인스턴스 메서드는 인스턴스 변수와 이에 액세스 할 수 있습니다. 다음 샘플의 <code>distanceTo()</code> 메서드는 인스턴스 메서드의 예시입니다.</p>
<pre><code class="language-dart">import &#39;dart:math&#39;;

class Point {
  double x, y;

  Point(this.x, this.y);

  double distanceTo(Point other) {
    var dx = x - other.x;
    var dy = y - other.y;
    return sqrt(dx * dx + dy * dy);
  }
}</code></pre>
<h4 id="getters-및-setters">Getters 및 setters</h4>
<p><code>Getter</code> 및 <code>Setter</code>는 개체 속성에 대한 읽기 및 쓰기 액세스를 제공하는 특수 메서드입니다. 각 인스턴스 변수에는 암시 적 <code>getter</code>와 적절한 경우 <code>setter</code> 가 있습니다. <code>get</code> 및 <code>set</code> 키워드를 사용하여 <code>getter</code> 및 <code>setter</code>를 구현하여 추가 속성을 만들 수 있습니다.</p>
<pre><code class="language-dart">class Rectangle {
  double left, top, width, height;

  Rectangle(this.left, this.top, this.width, this.height);

  // Define two calculated properties: right and bottom.
  double get right =&gt; left + width;
  set right(double value) =&gt; left = value - width;
  double get bottom =&gt; top + height;
  set bottom(double value) =&gt; top = value - height;
}

void main() {
  var rect = Rectangle(3, 4, 20, 15);
  assert(rect.left == 3);
  rect.right = 12;
  assert(rect.left == -8);
}</code></pre>
<p><code>getter</code> 및 <code>setter</code>를 사용하면 인스턴스 변수로 시작하고 나중에 클라이언트 코드를 변경하지 않고 메서드로 래핑 할 수 있습니다.</p>
<blockquote>
<p>증가(<code>++</code>)와 같은 연산자는 <code>getter</code>가 명시 적으로 정의되었는지 여부에 관계없이 예상 된 방식으로 작동합니다. 예기치 못한 부작용을 방지하기 위해 연산자는 <code>getter</code>를 정확히 한 번 호출하여 해당 값을 임시 변수에 저장합니다.</p>
</blockquote>
<h4 id="추상-메서드">추상 메서드</h4>
<p>인스턴스, <code>getter</code> 및 <code>setter</code> 메서드는 추상적 일 수 있으며 인터페이스를 정의하지만 구현은 다른 클래스에 맡깁니다. 추상 메서드는 _추상 클래스_에만 존재할 수 있습니다.</p>
<p>메서드를 추상적으로 만들려면 메서드 본문 대신 세미콜론 (<code>;</code>)을 사용합니다.</p>
<pre><code>abstract class Doer {
  // Define instance variables and methods...

  void doSomething(); // Define an abstract method.
}

class EffectiveDoer extends Doer {
  void doSomething() {
    // Provide an implementation, so the method is not abstract here...
  }
}</code></pre><h3 id="추상-클래스">추상 클래스</h3>
<p><code>abstract</code> 한정자를 사용하여 인스턴스화가 불가능한 추상 클래스를 정의합니다. 추상 클래스는 종종 일부 구현과 함께 인터페이스를 정의하는 데 유용합니다. 추상 클래스가 인스턴스화 가능한 것처럼 보이게하려면 _팩토리 생성자_를 정의하십시오.</p>
<p>추상 클래스에는 종종 _추상 메서드_가 있습니다. 다음은 _추상 메서드_가있는 추상 클래스를 선언하는 예시입니다.</p>
<pre><code class="language-dart">// This class is declared abstract and thus
// can&#39;t be instantiated.
abstract class AbstractContainer {
  // Define constructors, fields, methods...

  void updateChildren(); // Abstract method.
}</code></pre>
<h3 id="암묵적-인터페이스">암묵적 인터페이스</h3>
<p>모든 클래스는 클래스의 모든 인스턴스 멤버와 구현하는 인터페이스를 포함하는 인터페이스를 암시 적으로 정의합니다. B의 구현을 상속하지 않고 클래스 B의 API를 지원하는 클래스 A를 만들려면 클래스 A가 B 인터페이스를 구현해야합니다.</p>
<p>클래스는 하나 이상의 인터페이스를 _구현_절에서 선언 한 다음 인터페이스에 필요한 API를 제공하여 구현합니다. 예시를 들면,</p>
<pre><code class="language-dart">// A person. The implicit interface contains greet().
class Person {
  // In the interface, but visible only in this library.
  final _name;

  // Not in the interface, since this is a constructor.
  Person(this._name);

  // In the interface.
  String greet(String who) =&gt; &#39;Hello, $who. I am $_name.&#39;;
}

// An implementation of the Person interface.
class Impostor implements Person {
  get _name =&gt; &#39;&#39;;

  String greet(String who) =&gt; &#39;Hi $who. Do you know who I am?&#39;;
}

String greetBob(Person person) =&gt; person.greet(&#39;Bob&#39;);

void main() {
  print(greetBob(Person(&#39;Kathy&#39;)));
  print(greetBob(Impostor()));
}</code></pre>
<p>다음은 클래스가 여러 인터페이스를 구현하도록 지정하는 예시입니다.</p>
<pre><code class="language-dart">class Point implements Comparable, Location {...}</code></pre>
<h3 id="클래스-확장">클래스 확장</h3>
<p><code>extends</code>를 사용하여 하위 클래스를 만들고 <code>super</code>를 사용하여 수퍼 클래스를 참조합니다.</p>
<pre><code class="language-dart">class Television {
  void turnOn() {
    _illuminateDisplay();
    _activateIrSensor();
  }
  // ···
}

class SmartTelevision extends Television {
  void turnOn() {
    super.turnOn();
    _bootNetworkInterface();
    _initializeMemory();
    _upgradeApps();
  }
  // ···
}</code></pre>
<h4 id="멤버-재정의">멤버 재정의</h4>
<p>하위 클래스는 인스턴스 메서드, <code>getter</code> 및 <code>setter</code>를 재정의 할 수 있습니다. <code>@override</code> 주석을 사용하여 의도적으로 멤버를 재정의하고 있음을 나타낼 수 있습니다</p>
<pre><code class="language-dart">class SmartTelevision extends Television {
  @override
  void turnOn() {...}
  // ···
}</code></pre>
<p><a href="https://dart.dev/guides/language/type-system">형식이 안전한 코드</a>에서 메서드 매개 변수 또는 인스턴스 변수의 형식을 좁히려면 <a href="https://dart.dev/guides/language/sound-problems#the-covariant-keyword"><code>covariant</code> 키워드</a>를 사용할 수 있습니다.</p>
<h4 id="재정의-가능한-연산자">재정의 가능한 연산자</h4>
<p>다음 표에 표시된 연산자를 재정의 할 수 있습니다. 예를 들어 <em>Vector</em> 클래스를 정의하는 경우 <code>+</code> 메서드를 정의하여 두 개의 벡터를 추가 할 수 있습니다.</p>
<p><img src="https://images.velog.io/images/t0dd-kr/post/0941e6b7-b69a-4e6b-b92d-8b1b0e15c01d/image.png" alt=""></p>
<blockquote>
<p><code>!=</code> 가 재정의 할 수있는 연산자가 아니라는 것을 알 수 있습니다. <code>e1! = e2</code> 표현식은! (<code>e1 == e2</code>)에 대한 _문법적 설탕_입니다.</p>
</blockquote>
<p>다음은 <code>+</code> 및 <code>-</code> 연산자를 재정의하는 클래스의 예시입니다.</p>
<pre><code class="language-dart">class Vector {
  final int x, y;

  Vector(this.x, this.y);

  Vector operator +(Vector v) =&gt; Vector(x + v.x, y + v.y);
  Vector operator -(Vector v) =&gt; Vector(x - v.x, y - v.y);

  // Operator == and hashCode not shown. For details, see note below.
  // ···
}

void main() {
  final v = Vector(2, 3);
  final w = Vector(2, 2);

  assert(v + w == Vector(4, 5));
  assert(v - w == Vector(0, 1));
}</code></pre>
<p><code>==</code>를 재정의하는 경우 _Object_의 hashCode getter도 재정의해야합니다. == 및 hashCode를 재정의하는 예시는 <a href="https://dart.dev/guides/libraries/library-tour#implementing-map-keys">맵 키 구현</a>을 참조하세요.</p>
<p>일반적으로 재정의에 대한 자세한 내용은 <a href="https://dart.dev/guides/language/language-tour#extending-a-class">클래스 확장</a>을 참조하십시오.</p>
<h4 id="nosuchmethod">noSuchMethod()</h4>
<p>코드가 존재하지 않는 메서드 나 인스턴스 변수를 사용하려고 할 때마다 감지하거나 반응하려면 <code>noSuchMethod()</code>를 재정의 할 수 있습니다.</p>
<pre><code class="language-dart">class A {
  // Unless you override noSuchMethod, using a
  // non-existent member results in a NoSuchMethodError.
  @override
  void noSuchMethod(Invocation invocation) {
    print(&#39;You tried to use a non-existent member: &#39; +
        &#39;${invocation.memberName}&#39;);
  }
}</code></pre>
<p>다음 중 하나에 해당하지 않으면 구현되지 않은 메서드를 호출 할 수 없습니다.</p>
<ul>
<li><p>수신자는 동적 정적 유형을 갖습니다.</p>
</li>
<li><p>수신기에는 구현되지 않은 메서드를 정의하는 정적 유형이 있고 (추상은 괜찮음) 수신기의 동적 유형에는 Object 클래스의 것과 다른 <code>noSuchMethod()</code> 구현이 있습니다.</p>
</li>
</ul>
<p>자세한 내용은 비공식적 인 <a href="https://github.com/dart-lang/sdk/blob/master/docs/language/informal/nosuchmethod-forwarding.md"><code>noSuchMethod</code> 전달 사양</a>을 참조하세요.</p>
<h3 id="확장메서드">확장메서드</h3>
<p>Dart 2.7에 도입 된 _확장 메서드_는 기존 라이브러리에 기능을 추가하는 방법입니다. 자신도 모르게 확장 메서드를 사용할 수 있습니다. 예를 들어 IDE에서 코드 완성을 사용하는 경우 일반 메서드와 함께 확장 메서드를 제안합니다.</p>
<p>다음은 <code>string_apis.dart</code>에 정의 된 <code>parseInt()</code>라는 문자열에 확장 메서드를 사용하는 예시입니다.</p>
<pre><code class="language-dart">import &#39;string_apis.dart&#39;;
...
print(&#39;42&#39;.padLeft(5)); // Use a String method.
print(&#39;42&#39;.parseInt()); // Use an extension method.</code></pre>
<p>확장 메서드 사용 및 구현에 대한 자세한 내용은 <a href="https://dart.dev/guides/language/extension-methods">확장 메서드 페이지</a>를 참조하세요.</p>
<h3 id="열거-타입">열거 타입</h3>
<p>종종 <em>열거 타입</em> 또는 _열거 형_이라고 하는 열거 타입은 고정 된 수의 상수 값을 나타내는 데 사용되는 특수한 종류의 클래스입니다.</p>
<h4 id="열거-타입-사용">열거 타입 사용</h4>
<p><code>enum</code> 키워드를 사용하여 열거 타입을 선언합니다.</p>
<pre><code class="language-dart">enum Color { red, green, blue }</code></pre>
<p>열거 타입의 각 값에는 열거 타입 선언에서 값의 0부터 시작하는 위치를 반환하는 _인덱스 getter_가 있습니다. 예를 들어 첫 번째 인덱스 값은 0이고 두 번째 인덱스 값은 1입니다.</p>
<pre><code class="language-dart">assert(Color.red.index == 0);
assert(Color.green.index == 1);
assert(Color.blue.index == 2);</code></pre>
<p>열거 타입의 모든 값 목록을 가져 오려면 열거 타입의 값 상수를 사용합니다.</p>
<pre><code class="language-dart">List &lt;Color&gt; 색상 = Color.values;
assert (colors [2] == Color.blue);</code></pre>
<p><a href="https://dart.dev/guides/language/language-tour#switch-and-case"><code>switch</code> 문</a>에서 열거 타입을 사용할 수 있으며 열거 타입의 모든 값을 처리하지 않으면 경고가 표시됩니다.</p>
<pre><code class="language-dart">var aColor = Color.blue;

switch (aColor) {
  case Color.red:
    print(&#39;Red as roses!&#39;);
    break;
  case Color.green:
    print(&#39;Green as grass!&#39;);
    break;
  default: // Without this, you see a WARNING.
    print(aColor); // &#39;Color.blue&#39;
}</code></pre>
<p>열거 타입에는 다음과 같은 제한이 있습니다.</p>
<ul>
<li>열거 타입을 하위 클래스 화하거나 혼합하거나 구현할 수 없습니다.</li>
<li>열거 타입을 명시 적으로 인스턴스화 할 수 없습니다.</li>
</ul>
<p>자세한 내용은 Dart 언어 사양을 참조하세요.</p>
<h3 id="클래스에-기능-추가--mixins">클래스에 기능 추가 : mixins</h3>
<p>믹스 인은 여러 클래스 계층에서 클래스의 코드를 재사용하는 방법입니다.</p>
<p>믹스 인을 사용하려면 <code>with</code> 키워드 다음에 하나 이상의 믹스 인 이름을 사용하십시오. 다음 예제는 믹스 인을 사용하는 두 개의 클래스를 보여줍니다.</p>
<pre><code class="language-dart">class Musician extends Performer with Musical {
  // ···
}

class Maestro extends Person
    with Musical, Aggressive, Demented {
  Maestro(String maestroName) {
    name = maestroName;
    canConduct = true;
  }
}</code></pre>
<p>믹스 인을 구현하려면 _Object_를 확장하고 생성자를 선언하지 않는 클래스를 만듭니다. <code>mixin</code>을 일반 클래스로 사용하려면 <code>class</code> 대신 <code>mixin</code> 키워드를 사용하십시오. 예를 들면,</p>
<pre><code class="language-dart">mixin Musical {
  bool canPlayPiano = false;
  bool canCompose = false;
  bool canConduct = false;

  void entertainMe() {
    if (canPlayPiano) {
      print(&#39;Playing piano&#39;);
    } else if (canConduct) {
      print(&#39;Waving hands&#39;);
    } else {
      print(&#39;Humming to self&#39;);
    }
  }
}</code></pre>
<p>특정 유형 만 <code>mixin</code>을 사용할 수 있도록 지정하려면 (예: mixin이 정의하지 않은 메소드를 호출 할 수 있도록) <code>on</code>을 사용하여 필수 수퍼 클래스를 지정하십시오.</p>
<pre><code class="language-dart">mixin MusicalPerformer on Musician {
  // ···
}</code></pre>
<blockquote>
<p><code>mixin</code> 키워드에 대한 지원은 Dart 2.1에서 도입되었습니다. 이전 릴리스의 코드는 일반적으로 _추상 클래스_를 대신 사용했습니다. 2.1 믹스 인 변경에 대한 자세한 내용은 <a href="https://github.com/dart-lang/sdk/blob/master/CHANGELOG.md">Dart SDK 변경 로그</a> 및 <a href="https://github.com/dart-lang/language/blob/master/accepted/2.1/super-mixins/feature-specification.md#dart-2-mixin-declarations">2.1 믹스 인 사양</a>을 참조하세요.</p>
</blockquote>
<h3 id="클래스-변수-및-메서드">클래스 변수 및 메서드</h3>
<p><code>static</code> 키워드를 사용하여 클래스 전체 변수 및 메서드를 구현합니다.</p>
<h4 id="정적-변수">정적 변수</h4>
<p>정적 변수 (클래스 변수)는 클래스 전체 상태 및 상수에 유용합니다.</p>
<pre><code class="language-dart">class Queue {
  static const initialCapacity = 16;
  // ···
}

void main() {
  assert(Queue.initialCapacity == 16);
}</code></pre>
<p>정적 변수는 사용될 때까지 초기화되지 않습니다.</p>
<blockquote>
<p>이 페이지는 상수 이름에 대해 _lowerCamelCase_를 선호하는 <a href="https://dart.dev/guides/language/effective-dart/style#identifiers">스타일 가이드 권장 사항</a>을 따릅니다.</p>
</blockquote>
<h4 id="정적-메서드">정적 메서드</h4>
<p>정적 메서드 (클래스 메서드)는 인스턴스에서 작동하지 않으므로 이에 대한 액세스 권한이 없습니다. 예를 들면,</p>
<pre><code class="language-dart">import &#39;dart:math&#39;;

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

  static double 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 &lt; distance &amp;&amp; distance &lt; 2.9);
  print(distance);
}</code></pre>
<blockquote>
<p>일반적이거나 널리 사용되는 유틸리티 및 기능에 대해 정적 메서드 대신 최상위 수준 함수를 사용하는 것이 좋습니다.</p>
</blockquote>
<p>정적 메서드를 컴파일 타임 상수로 사용할 수 있습니다. 예를 들어 정적 메서드를 상수 생성자에 매개 변수로 전달할 수 있습니다.</p>
]]></description>
        </item>
        <item>
            <title><![CDATA[Dart Language Tour #5]]></title>
            <link>https://velog.io/@t0dd-kr/Dart-Language-Tour-5</link>
            <guid>https://velog.io/@t0dd-kr/Dart-Language-Tour-5</guid>
            <pubDate>Thu, 24 Sep 2020 08:30:41 GMT</pubDate>
            <description><![CDATA[<h2 id="흐름제어문">흐름제어문</h2>
<p>다음 중 하나를 사용하여 Dart 코드의 흐름을 제어 할 수 있습니다.</p>
<ul>
<li><code>if</code> 와 <code>else</code></li>
<li><code>for</code> 반복문</li>
<li><code>white</code>과 <code>do-while</code> 반복문</li>
<li><code>break</code>과 <code>continue</code></li>
<li><code>switch</code>와 <code>case</code>문</li>
<li><code>assert</code></li>
</ul>
<p><a href="https://dart.dev/guides/language/language-tour#exceptions">예외</a>에 설명 된대로 <code>try-catch</code> 및 <code>throw</code>를 사용하여 흐름제어에 영향을 줄 수도 있습니다.</p>
<h3 id="if와-else">if와 else</h3>
<p>Dart는 아래 샘플에서 볼 수 있듯이 선택적 <code>else</code> 문이있는 <code>if</code> 문을 지원합니다. <a href="https://dart.dev/guides/language/language-tour#conditional-expressions">조건식</a>도 참조하십시오.</p>
<pre><code class="language-dart">if (isRaining()) {
  you.bringRainCoat();
} else if (isSnowing()) {
  you.wearJacket();
} else {
  car.putTopDown();
}</code></pre>
<p>_JavaScript_와 달리 조건식은 부울 값을 사용해야합니다. 자세한 내용은 <a href="https://dart.dev/guides/language/language-tour#booleans">부울</a>을 참조하십시오.</p>
<h3 id="for">for</h3>
<p>일반적인 <code>for</code> 문으로 반복할 수 있습니다. 예시를 들면</p>
<pre><code class="language-dart">var message = StringBuffer(&#39;Dart is fun&#39;);
for (var i = 0; i &lt; 5; i++) {
  message.write(&#39;!&#39;);
}</code></pre>
<p>Dart <code>for</code>문 내부의 클로저는 인덱스의 가치를 포착하여 _Javascript_에서 발견되는 일반적인 함정을 피합니다. 예를 들어 다음을 고려하십시오.</p>
<pre><code class="language-dart">var callbacks = [];
for (var i = 0; i &lt; 2; i++) {
  callbacks.add(() =&gt; print(i));
}
callbacks.forEach((c) =&gt; c());</code></pre>
<p>예상대로 출력은 0과 1입니다. 반대로 이 예제는 _Javascript_에서 2를 인쇄 한 다음 2를 인쇄합니다.</p>
<p>반복하는 객체가 _Iterable_이면 <code>forEach()</code> 메서드를 사용할 수 있습니다. 현재 반복 카운터를 알 필요가 없는 경우 <code>forEach()</code>를 사용하는 것이 좋습니다.</p>
<pre><code class="language-dart">candidates.forEach((candidate) =&gt; candidate.interview());</code></pre>
<p><em>List</em> 및 _Set_과 같은 반복 가능한 클래스는 <code>for-in</code> 형식의 반복도 지원합니다.</p>
<pre><code class="language-dart">var collection = [1, 2, 3];
for (var x in collection) {
  print(x); // 1 2 3
}</code></pre>
<h3 id="while-과-do-while">while 과 do-while</h3>
<p><code>while</code>문은 반복 이전에 조건을 평가합니다.</p>
<pre><code class="language-dart">while (!isDone()) {
  doSomething();
}</code></pre>
<p><code>do-while</code>문는 반복 이후에 조건을 평가합니다.</p>
<pre><code class="language-dart">do {
  printLine();
} while (!atEndOfPage());</code></pre>
<h3 id="break-과-continue">break 과 continue</h3>
<p>반복을 중지하려면 <code>break</code>를 사용합니다.</p>
<pre><code class="language-dart">while (true) {
  if (shutDownRequested()) break;
  processIncomingRequests();
}</code></pre>
<p>다음 반복으로 건너 뛰려면 <code>continue</code>를 사용하십시오.</p>
<pre><code class="language-dart">for (int i = 0; i &lt; candidates.length; i++) {
  var candidate = candidates[i];
  if (candidate.yearsExperience &lt; 5) {
    continue;
  }
  candidate.interview();
}</code></pre>
<p><em>List</em> 또는 _Set_와 같은 _Iterable_을 사용하는 경우, 이 예제를 다르게 작성할 수 있습니다.</p>
<pre><code class="language-dart">candidates
    .where((c) =&gt; c.yearsExperience &gt;= 5)
    .forEach((c) =&gt; c.interview());</code></pre>
<h3 id="switch-와-case">switch 와 case</h3>
<p>Dart의 <code>switch</code> 문은 <code>==</code>를 사용하여 정수, 문자열 또는 컴파일 시간 상수를 비교합니다. 비교 된 객체는 모두 동일한 클래스의 인스턴스 여야하며 (하위 유형이 아님) 클래스가 <code>==</code>를 재정의해서는 안됩니다. 열거 형은 <code>switch</code> 문에서 잘 작동합니다.</p>
<blockquote>
<p>Dart의 Switch 문은 통역사 또는 스캐너와 같은 제한된 상황을위한 것입니다.</p>
</blockquote>
<p>비어 있지 않은 각 <code>case</code> 문은 일반적으로 <code>break</code> 문으로 끝납니다. 비어 있지 않은 <code>case</code> 문을 종료하는 다른 유효한 방법은 <code>continue</code>, <code>throw</code> 또는 <code>return</code> 문입니다.</p>
<p><code>case</code> 문이 일치하지 않을 때 <code>default</code> 문을 사용하여 코드를 실행합니다.</p>
<pre><code class="language-dart">var command = &#39;OPEN&#39;;
switch (command) {
  case &#39;CLOSED&#39;:
    executeClosed();
    break;
  case &#39;PENDING&#39;:
    executePending();
    break;
  case &#39;APPROVED&#39;:
    executeApproved();
    break;
  case &#39;DENIED&#39;:
    executeDenied();
    break;
  case &#39;OPEN&#39;:
    executeOpen();
    break;
  default:
    executeUnknown();
}</code></pre>
<p>다음 예시에서는 <code>case</code> 절에서 <code>break</code> 문을 생략하여 오류를 생성합니다.</p>
<pre><code class="language-dart">var command = &#39;OPEN&#39;;
switch (command) {
  case &#39;OPEN&#39;:
    executeOpen();
    // ERROR: Missing break

  case &#39;CLOSED&#39;:
    executeClosed();
    break;
}</code></pre>
<p>그러나 Dart는 빈 <code>case</code> 문을 지원하여 다음과 같은 폴 스루 형식을 허용합니다.</p>
<pre><code class="language-dart">var command = &#39;CLOSED&#39;;
switch (command) {
  case &#39;CLOSED&#39;: // Empty case falls through.
  case &#39;NOW_CLOSED&#39;:
    // Runs for both CLOSED and NOW_CLOSED.
    executeNowClosed();
    break;
}</code></pre>
<p>정말로 폴 스루를 원한다면 <code>continue</code> 문과 레이블을 사용할 수 있습니다.</p>
<pre><code class="language-dart">var command = &#39;CLOSED&#39;;
switch (command) {
  case &#39;CLOSED&#39;:
    executeClosed();
    continue nowClosed;
  // Continues executing at the nowClosed label.

  nowClosed:
  case &#39;NOW_CLOSED&#39;:
    // Runs for both CLOSED and NOW_CLOSED.
    executeNowClosed();
    break;
}</code></pre>
<p><code>case</code> 문에는 해당 문의 범위 내에서만 볼 수 있는 지역 변수가 있을 수 있습니다.</p>
<h3 id="assert">assert</h3>
<p>개발 중에는 <code>assert</code> 문을 사용하십시오 — <code>assert (condition, optionalMessage);</code> — 부울 조건이 거짓 인 경우 정상적인 실행을 방해합니다. 이 둘러보기를 통해 <code>assert</code> 문 예제를 찾을 수 있습니다. 다음은 몇 가지 더 있습니다.</p>
<pre><code class="language-dart">// 변수에 null이 아닌 값이 있는지 확인하십시오.
assert(text != null);

// 변수가 100보다 작은지 확인하십시오.
assert(number &lt; 100);

// https URL인지 확인하십시오.
assert(urlString.startsWith(&#39;https&#39;));</code></pre>
<p><code>assert</code>에 메시지를 첨부하려면 <code>assert</code> 할 두 번째 인수로 문자열을 추가합니다.</p>
<pre><code class="language-dart">assert(urlString.startsWith(&#39;https&#39;),
    &#39;URL ($urlString) should start with &quot;https&quot;.&#39;);</code></pre>
<p>주장 할 첫 번째 인수는 부울 값으로 확인되는 모든 표현식이 될 수 있습니다. 식의 값이<code>true</code> 이면 _Assertion_이 성공하고 실행이 계속됩니다. <code>false</code> 이면 _Assertion_이 실패하고 _예외 (<a href="https://api.dart.dev/stable/dart-core/AssertionError-class.html">AssertionError</a>)_가 발생합니다.</p>
<p>_Assertion_은 정확히 언제 작동합니까? 사용중인 도구와 프레임 워크에 따라 다릅니다.</p>
<ul>
<li>_Flutter_는 디버그 모드에서 _Assertion_을 활성화합니다.</li>
<li>_dartdevc_와 같은 개발 전용 도구는 일반적으로 기본적으로 _Assertion_을 활성화합니다.</li>
<li><em>dart</em> 및 _dart2js_와 같은 일부 도구는 명령 줄 플래그 <code>--enable-asserts</code>를 통해 _Assertion_을 지원합니다.</li>
</ul>
<p>프로덕션 코드에서는 <em>Assertion_이 무시되고 _Assertion</em> 할 인수가 평가되지 않습니다.</p>
<h2 id="예외처리">예외처리</h2>
<p>Dart 코드는 예외를 발생시키고 포착 할 수 있습니다. 예외는 예기치 않은 일이 발생했음을 나타내는 오류입니다. 예외가 포착되지 않으면 예외를 발생시킨 <a href="https://dart.dev/guides/language/language-tour#isolates">격리</a>가 일시 중지되고 일반적으로 격리와 해당 프로그램이 종료됩니다.</p>
<p>Java와 달리 Dart의 모든 예외는 확인되지 않은 예외입니다. 메서드는 <code>throw</code> 할 수있는 예외를 선언하지 않으며 예외를 포착 할 필요가 없습니다.</p>
<p>Dart는 <a href="https://api.dart.dev/stable/dart-core/Exception-class.html">Exception</a> 및 <a href="https://api.dart.dev/stable/dart-core/Error-class.html">Error</a> 유형은 물론 사전 정의 된 수많은 하위 유형을 제공합니다. 물론 자신 만의 예외를 정의 할 수 있습니다. 그러나 Dart 프로그램은 <em>Exception</em> 및 <em>Error</em> 개체뿐만 아니라 <code>null</code>이 아닌 개체를 예외로 <code>throw</code> 할 수 있습니다.</p>
<h3 id="throw">Throw</h3>
<p>다음은 예외를 던지거나 발생시키는 예시입니다.</p>
<pre><code class="language-dart">throw FormatException(&#39;Expected at least 1 section&#39;);
throw &#39;Out of llamas!&#39;; // 임의의 객체를 던질 수도 있습니다.</code></pre>
<blockquote>
<p>프로덕션 품질 코드는 일반적으로 오류 또는 예외를 구현하는 유형을 발생시킵니다.</p>
</blockquote>
<p>예외를 던지는 것은 표현식이므로 <code>=&gt;</code> 문은 물론 표현식을 허용하는 다른 모든 곳에서 예외를 던질 수 있습니다.</p>
<pre><code class="language-dart">void distanceTo(Point other) =&gt; throw UnimplementedError();</code></pre>
<h3 id="catch">Catch</h3>
<p>예외를 포착나 캡처하면 예외가 전파되는 것을 중지합니다 (예외를 다시 던지지 않는 한). 예외를 포착하면 처리 할 수있는 기회가 제공됩니다.</p>
<pre><code class="language-dart">try {
  breedMoreLlamas();
} on OutOfLlamasException {
  buyMoreLlamas();
}</code></pre>
<p>둘 이상의 예외 유형을 발생시킬 수있는 코드를 처리하기 위해 여러 <code>catch</code> 절을 지정할 수 있습니다. <code>throw</code> 된 객체의 유형과 일치하는 첫 번째 <code>catch</code> 절이 예외를 처리합니다. <code>catch</code> 절이 유형을 지정하지 않으면 해당 절은 모든 유형의 throw 된 객체를 처리 할 수 있습니다.</p>
<pre><code class="language-dart">try {
  breedMoreLlamas();
} on OutOfLlamasException {
  // A specific exception
  buyMoreLlamas();
} on Exception catch (e) {
  // Anything else that is an exception
  print(&#39;Unknown exception: $e&#39;);
} catch (e) {
  // No specified type, handles all
  print(&#39;Something really unknown: $e&#39;);
}</code></pre>
<p>앞의 코드에서 볼 수 있듯이 <code>on</code>, <code>catch</code> 또는 둘 다를 사용할 수 있습니다. 예외 유형을 지정해야 할 때 <code>on</code>을 사용하십시오. 예외 처리기에 예외 개체가 필요한 경우 <code>catch</code>를 사용합니다.</p>
<p><code>catch()</code>에 하나 또는 두 개의 매개 변수를 지정할 수 있습니다. 첫 번째는 <code>throw</code> 된 예외이고 두 번째는 스택 추적 (<em>StackTrace</em> 객체)입니다.</p>
<pre><code class="language-dart">try {
  // ···
} on Exception catch (e) {
  print(&#39;Exception details:\n $e&#39;);
} catch (e, s) {
  print(&#39;Exception details:\n $e&#39;);
  print(&#39;Stack trace:\n $s&#39;);
}</code></pre>
<p>예외를 부분적으로 처리하고 전파를 허용하려면 <code>rethrow</code> 키워드를 사용하십시오.</p>
<pre><code class="language-dart">void misbehave() {
  try {
    dynamic foo = true;
    print(foo++); // 런타임 에러
  } catch (e) {
    print(&#39;misbehave() partially handled ${e.runtimeType}.&#39;);
    rethrow; // 에러의 전파 허용
  }
}

void main() {
  try {
    misbehave(); // 에러 전파로 인한 에러 발생
  } catch (e) {
    print(&#39;main() finished handling ${e.runtimeType}.&#39;);
  }
}</code></pre>
<h3 id="finally">Finally</h3>
<p>예외 발생 여부에 관계없이 일부 코드가 실행되도록하려면 <code>finally</code>절을 사용하십시오. 예외와 일치하는 <code>catch</code> 절이 없으면 <code>finally</code> 절이 실행 된 후 예외가 전파됩니다.</p>
<pre><code class="language-dart">`try {
  breedMoreLlamas();
} finally {
  // Always clean up, even if an exception is thrown.
  cleanLlamaStalls();
}</code></pre>
<p><code>finally</code> 절은 일치하는 <code>catch</code> 절 이후에 실행됩니다.</p>
<pre><code class="language-dart">try {
  breedMoreLlamas();
} catch (e) {
  print(&#39;Error: $e&#39;); // Handle the exception first.
} finally {
  cleanLlamaStalls(); // Then clean up.
}</code></pre>
<p>라이브러리 둘러보기의 <a href="https://dart.dev/guides/libraries/library-tour#exceptions">예외</a> 섹션을 읽고 자세히 알아보세요.</p>
]]></description>
        </item>
        <item>
            <title><![CDATA[Dart Language Tour #4]]></title>
            <link>https://velog.io/@t0dd-kr/Dart-Language-Tour-4</link>
            <guid>https://velog.io/@t0dd-kr/Dart-Language-Tour-4</guid>
            <pubDate>Tue, 01 Sep 2020 09:03:55 GMT</pubDate>
            <description><![CDATA[<h2 id="연산자">연산자</h2>
<p>Dart는 아래 표에 표시된 연산자를 정의합니다. <a href="https://dart.dev/guides/language/language-tour#overridable-operators">재정의 가능한 연산자</a>에 설명 된대로 이러한 연산자 중 다수를 재정의 할 수 있습니다.</p>
<p><img src="https://images.velog.io/images/t0dd-kr/post/41e24dc5-a4c7-4dda-87e6-2aea09939a4b/image.png" alt="Dart Operators"></p>
<blockquote>
<p><strong>주의:</strong> 
연산자 우선 순위는 Dart 파서 동작의 근사치입니다. 확실한 답은 <a href="https://dart.dev/guides/language/spec">Dart 언어 사양</a>의 문법을 참조하십시오.</p>
</blockquote>
<p>연산자를 사용하면 표현식이 생성됩니다. 다음은 연산자 표현식의 몇 가지 예시입니다.</p>
<pre><code class="language-dart">a++
a + b
a = b
a == b
c ? a : b
a is T</code></pre>
<p>연산자 테이블에서 각 연산자는 뒤에 오는 행의 연산자보다 우선 순위가 높습니다. 예를 들어 곱셈 연산자 <code>%</code>는 논리 <code>AND</code> 연산자 <code>&amp;&amp;</code>보다 우선 순위가 높은 같음 연산자 <code>==</code>보다 우선 순위가 더 높습니다 (따라서 이전에 실행 됨). 이 우선 순위는 다음 두 줄의 코드가 동일한 방식으로 실행됨을 의미합니다.</p>
<pre><code class="language-dart">// 괄호로 가독성을 향상시킵니다.
if ((n % i == 0) &amp;&amp; (d % i == 0)) ...

// 가독성이 떨어지지만, 같은 논리식입니다.
if (n % i == 0 &amp;&amp; d % i == 0) ...</code></pre>
<blockquote>
<p><strong>주의:</strong> 두 개의 피연산자에 대해 작업하는 연산자의 경우 가장 왼쪽에있는 피연산자가 사용되는 연산자 버전을 결정합니다. 예를 들어 <em>Vector</em> 객체와 <em>Point</em> 객체가있는 경우 <code>aVector + aPoint</code>는 <em>Vector</em> 버전의 <code>+</code>를 사용합니다.</p>
</blockquote>
<h3 id="산술연산자">산술연산자</h3>
<p>Dart는 다음 표와 같이 일반적인 산술 연산자를 지원합니다.
<img src="https://images.velog.io/images/t0dd-kr/post/a0cea7c7-1ece-4293-8a87-f16088be2683/image.png" alt=""></p>
<pre><code class="language-dart">assert(2 + 3 == 5);
assert(2 - 3 == -1);
assert(2 * 3 == 6);
assert(5 / 2 == 2.5); // Result is a double
assert(5 ~/ 2 == 2); // Result is an int
assert(5 % 2 == 1); // Remainder

assert(&#39;5/2 = ${5 ~/ 2} r ${5 % 2}&#39; == &#39;5/2 = 2 r 1&#39;);</code></pre>
<p>Dart는 또한 접두사 및 접미사 증가 및 감소 연산자를 모두 지원합니다.</p>
<p><img src="https://images.velog.io/images/t0dd-kr/post/41bc975c-364a-41fd-9aa1-8dbfafaf9721/image.png" alt=""></p>
<pre><code class="language-dart">var a, b;

a = 0;
b = ++a; // Increment a before b gets its value.
assert(a == b); // 1 == 1

a = 0;
b = a++; // Increment a AFTER b gets its value.
assert(a != b); // 1 != 0

a = 0;
b = --a; // Decrement a before b gets its value.
assert(a == b); // -1 == -1

a = 0;
b = a--; // Decrement a AFTER b gets its value.
assert(a != b); // -1 != 0</code></pre>
<h3 id="평등-및-관계-연산자">평등 및 관계 연산자</h3>
<p>다음 표에는 같음 및 관계 연산자의 의미가 나열되어 있습니다.</p>
<p><img src="https://images.velog.io/images/t0dd-kr/post/68f40b15-e0f7-4114-a8f1-5f7b4dc4fcc7/image.png" alt=""></p>
<p>두 객체 <code>x</code>와 <code>y</code>가 같은 것을 나타내는 지 테스트하려면 <code>==</code> 연산자를 사용하십시오. (드물게 두 객체가 정확히 동일한 객체인지 알아야하는 경우에는 대신 <code>same()</code> 함수를 사용하십시오.) <code>==</code> 연산자의 작동 방식은 다음과 같습니다.</p>
<ul>
<li><code>x</code> 또는 <code>y</code>가 둘 다 <code>null</code>이면 <code>true</code>를 반환하고 하나만 <code>null</code>이면 <code>false</code>를 반환합니다.</li>
<li>메서드 호출 <code>x. == (y)</code>의 결과를 반환합니다. (맞습니다. <code>==</code>와 같은 연산자는 첫 번째 피연산자에서 호출되는 메서드입니다. 재정의 가능 연산자에서 볼 수 있듯이 <code>==</code>를 비롯한 많은 연산자를 재정의 할 수도 있습니다.)</li>
</ul>
<p>다음은 같음 및 관계 연산자를 각각 사용하는 예입니다.</p>
<pre><code class="language-dart">assert(2 == 2);
assert(2 != 3);
assert(3 &gt; 2);
assert(2 &lt; 3);
assert(3 &gt;= 3);
assert(2 &lt;= 3);</code></pre>
<h3 id="유형-테스트-연산자">유형 테스트 연산자</h3>
<p><code>as</code>, <code>is</code>, <code>is!</code> 연산자는 런타임에 유형을 확인하는 데 편리합니다.</p>
<p><img src="https://images.velog.io/images/t0dd-kr/post/fbfa9ed7-dc7c-42bd-9bb6-f6b3cb614f5f/image.png" alt=""></p>
<p><code>obj is T</code>로 지정된 인터페이스를 구현하는 경우 <code>obj</code>의 결과는 <code>T</code>가 <code>true</code>입니다. 예를 들어 <code>obj is Object</code>가 항상 <code>true</code>입니다.</p>
<p>객체가 해당 유형인지 확신하는 경우에만 <code>as</code> 연산자를 사용하여 객체를 특정 유형으로 캐스트하십시오.</p>
<pre><code class="language-dart">(emp as Person).firstName = &#39;Bob&#39;;</code></pre>
<p>개체가 <em>T</em> 유형인지 확실하지 않은 경우 개체를 사용하기 전에 <code>is T</code>를 사용하여 유형을 확인합니다.</p>
<pre><code class="language-dart">if (emp is Person) {
  // Type check
  emp.firstName = &#39;Bob&#39;;
}</code></pre>
<blockquote>
<p>코드가 동일하지 않습니다. <code>emp</code>가 <code>null</code>이거나 <code>Person</code>이 아니면 첫 번째 예제는 예외를 던집니다. 두 번째는 아무것도 하지 않습니다.</p>
</blockquote>
<h3 id="할당-연산자">할당 연산자</h3>
<p>이미 살펴본 것처럼 <code>=</code> 연산자를 사용하여 값을 할당 할 수 있습니다. 할당 대상 변수가 <code>null</code> 인 경우에만 할당하려면 <code>??=</code> 연산자를 사용합니다.</p>
<pre><code class="language-dart">// Assign value to a
a = value;
// Assign value to b if b is null; otherwise, b stays the same
b ??= value;</code></pre>
<p><code>+=</code>와 같은 복합 할당 연산자는 연산과 할당을 결합합니다.</p>
<p><img src="https://images.velog.io/images/t0dd-kr/post/de43bfad-fe76-4506-bd22-351fa120deef/image.png" alt=""></p>
<p>복합 할당 연산자의 작동 방식은 다음과 같습니다.</p>
<p><img src="https://images.velog.io/images/t0dd-kr/post/131566ae-216f-4f15-b196-4d4f4709a36f/image.png" alt=""></p>
<p>다음 예에서는 할당 및 복합 할당 연산자를 사용합니다.</p>
<pre><code class="language-dart">var a = 2; // Assign using =
a *= 3; // Assign and multiply: a = a * 3
assert(a == 6);</code></pre>
<h3 id="논리-연산자">논리 연산자</h3>
<p>논리 연산자를 사용하여 부울 식을 반전하거나 결합 할 수 있습니다.</p>
<p><img src="https://images.velog.io/images/t0dd-kr/post/60f32eca-8e16-4891-a14f-a2efd8820542/image.png" alt=""></p>
<p>다음은 논리 연산자를 사용하는 예입니다.</p>
<pre><code class="language-dart">if (!done &amp;&amp; (col == 0 || col == 3)) {
  // ...Do something...
}</code></pre>
<h3 id="비트-및-시프트-연산자">비트 및 시프트 연산자</h3>
<p>Dart에서 개별 숫자 비트를 조작 할 수 있습니다. 일반적으로 정수와 함께 이러한 비트 및 시프트 연산자를 사용합니다.</p>
<p><img src="https://images.velog.io/images/t0dd-kr/post/66801b5c-cac3-46d9-836f-e950594628d9/image.png" alt=""></p>
<p>다음은 비트 및 시프트 연산자를 사용하는 예입니다.</p>
<pre><code class="language-dart">final value = 0x22;
final bitmask = 0x0f;

assert((value &amp; bitmask) == 0x02); // AND
assert((value &amp; ~bitmask) == 0x20); // AND NOT
assert((value | bitmask) == 0x2f); // OR
assert((value ^ bitmask) == 0x2d); // XOR
assert((value &lt;&lt; 4) == 0x220); // Shift left
assert((value &gt;&gt; 4) == 0x02); // Shift right</code></pre>
<h3 id="조건식">조건식</h3>
<p>Dart에는 <em>if-else</em> 문이 필요할 수있는 표현식을 간결하게 평가할 수있는 두 개의 연산자가 있습니다.</p>
<pre><code class="language-dart">condition ? expr1 : expr2</code></pre>
<p>조건이 참이면 <code>expr1</code>을 평가하고 그 값을 반환합니다. 그렇지 않으면 <code>expr2</code>의 값을 평가하고 반환합니다.</p>
<pre><code class="language-dart">expr1 ?? expr2</code></pre>
<p><code>expr1</code>이 <code>null</code>이 아니면 값을 리턴합니다. 그렇지 않으면 <code>expr2</code>의 값을 평가하고 반환합니다.</p>
<p>부울 표현식을 기반으로 값을 할당해야하는 경우 <code>? ~ :</code> 사용을 고려하십시오.</p>
<pre><code class="language-dart">var visibility = isPublic ? &#39;public&#39; : &#39;private&#39;;</code></pre>
<p>부울식이 <code>null</code>을 테스트하는 경우 <code>??</code>를 사용하는 것이 좋습니다.</p>
<pre><code class="language-dart">String playerName(String name) =&gt; name ?? &#39;Guest&#39;;</code></pre>
<p>위 예제는 적어도 두 가지 다른 방법으로 작성되었을 수 있지만 간결하지는 않습니다.</p>
<pre><code class="language-dart">// Slightly longer version uses ?: operator.
String playerName(String name) =&gt; name != null ? name : &#39;Guest&#39;;

// Very long version uses if-else statement.
String playerName(String name) {
  if (name != null) {
    return name;
  } else {
    return &#39;Guest&#39;;
  }
}</code></pre>
<h3 id="캐스케이드-표기법-">캐스케이드 표기법 <code>(..)</code></h3>
<p>캐스케이드 <code>(..)</code>를 사용하면 동일한 개체에서 일련의 작업을 수행 할 수 있습니다. 함수 호출 외에도 동일한 객체의 필드에 액세스 할 수 있습니다. 이것은 종종 임시 변수를 만드는 단계를 절약하고 더 유동적 인 코드를 작성할 수있게합니다.</p>
<p>아래 코드를 보면, </p>
<pre><code class="language-dart">querySelector(&#39;#confirm&#39;) // Get an object.
  ..text = &#39;Confirm&#39; // Use its members.
  ..classes.add(&#39;important&#39;)
  ..onClick.listen((e) =&gt; window.alert(&#39;Confirmed!&#39;));</code></pre>
<p>첫 번째 메서드 호출 인 <code>querySelector()</code>는 선택기 객체를 반환합니다. 계단식 표기법을 따르는 코드는 반환 될 수있는 모든 후속 값을 무시하고이 선택기 개체에서 작동합니다.</p>
<p>위 예시는 다음과 같습니다.</p>
<pre><code class="language-dart">var sb = StringBuffer();
sb.write(&#39;foo&#39;)
  ..write(&#39;bar&#39;); // Error: method &#39;write&#39; isn&#39;t defined for &#39;void&#39;.</code></pre>
<p><code>sb.write()</code> 호출은 <code>void</code>를 반환하며 <code>void</code>에 계단식을 구성할 수 없습니다.</p>
<blockquote>
<p>엄밀히 말해서 캐스케이드에 대한 &quot;이중 점&quot; 표기법은 연산자가 아닙니다. Dart 구문의 일부 일 뿐입니다.</p>
</blockquote>
<h3 id="기타-연산자">기타 연산자</h3>
<p>다른 예시에서 나머지 연산자의 대부분을 확인했습니다.</p>
<p><img src="https://images.velog.io/images/t0dd-kr/post/97c1920a-2e90-4b7f-aa23-8256760d5478/image.png" alt=""></p>
<p><code>.</code>, <code>?.</code> 및 <code>..</code> 연산자에 대한 자세한 내용은 <a href="https://dart.dev/guides/language/language-tour#classes">클래스</a>를 참조하십시오.</p>
]]></description>
        </item>
        <item>
            <title><![CDATA[Dart Language Tour #3]]></title>
            <link>https://velog.io/@t0dd-kr/Dart-Language-Tour-3</link>
            <guid>https://velog.io/@t0dd-kr/Dart-Language-Tour-3</guid>
            <pubDate>Mon, 31 Aug 2020 08:53:55 GMT</pubDate>
            <description><![CDATA[<h2 id="functions">Functions</h2>
<p>Dart는 진정한 객체지향 언어이므로 함수조차도 객체이고 타입인 _Function_을 갖습니다. 이는 함수를 변수에 할당하거나 다른 함수에 인수로 전달할 수 있음을 의미합니다. 함수인 것처럼 Dart 클래스의 인스턴스를 호출할 수도 있습니다. 자세한 내용은 <code>Callable</code> 클래스를 참조하십시오.</p>
<p>다음은 함수 구현의 예입니다.</p>
<pre><code class="language-dart">bool isNoble(int atomicNumber) {
  return _nobleGases[atomicNumber] != null;
}</code></pre>
<p>Dart를 효율적으로 사용하기 위해서는 <a href="https://dart.dev/guides/language/effective-dart/design#prefer-type-annotating-public-fields-and-top-level-variables-if-the-type-isnt-obvious">공용 API에 대한 타입 명시</a>을 권장하지만 타입 명시를 생략해도 함수는 계속 작동합니다.</p>
<pre><code class="language-dart">isNoble(atomicNumber) {
  return _nobleGases[atomicNumber] != null;
}</code></pre>
<p>표현식이 하나만 포함 된 함수의 경우 약식 구문을 사용할 수 있습니다.</p>
<pre><code class="language-dart">bool isNoble(int atomicNumber) =&gt; _nobleGases[atomicNumber] != null;</code></pre>
<p><code>=&gt; expr</code> 구문은 <code>{return expr; }</code>. <code>=&gt;</code> 표기법은 때때로 _화살표구문_이라고도합니다.</p>
<blockquote>
<p>구문이 아닌 표현식만 화살표 <code>=&gt;</code>와 세미콜론 <code>;</code> 사이에 나타날 수 있습니다. 예를 들어 여기에 <code>if</code> 문을 넣을 수 없지만 조건식을 사용할 수 있습니다.</p>
</blockquote>
<p>함수는 필수 및 선택의 두 가지 유형의 매개변수를 가질 수 있습니다. 필수 매개변수가 먼저 나열되고 그 뒤에 선택적 매개변수가 나열됩니다. 선택적 매개변수는 이름이 지정되거나 위치가 지정될 수 있습니다.</p>
<blockquote>
<p>일부 API (특히 Flutter 위젯 생성자)는 필수 매개변수에 대해서도 명시 된 매개변수만 사용합니다. 자세한 내용은 다음 섹션을 참조하십시오.</p>
</blockquote>
<h3 id="선택적-매개변수">선택적 매개변수</h3>
<p>선택적 매개변수는 이름 또는 위치가 될 수 있지만 둘 다는 아닙니다.</p>
<h4 id="명시적-매개변수">명시적 매개변수</h4>
<p>함수를 호출할 때 <code>paramName: value</code>를 사용하여 매개변수를 지정할 수 있습니다. 예를 들어</p>
<pre><code class="language-dart">enableFlags(bold: true, hidden: false);</code></pre>
<p>함수를 정의할 때 <code>{param1, param2, ...}</code> 를 사용하여 명시적 매개변수를 지정합니다.</p>
<pre><code class="language-dart">/// Sets the [bold] and [hidden] flags ...
void enableFlags({bool bold, bool hidden}) {...}</code></pre>
<p>명시적 매개변수는 일종의 선택적 매개변수이지만 매개변수가 필수임을 나타내기 위해 <code>@required</code>로 주석을 달 수 있습니다. 사용자는 매개변수에 대한 값을 제공해야합니다. 예를 들면 :</p>
<pre><code class="language-dart">const Scrollbar({Key key, @required Widget child})</code></pre>
<p>만약 자식인자를 지정하지 않고 스크롤바를 만들려고 하면 분석기가 문제를 보고합니다.</p>
<p><code>@required</code> 주석을 사용하려면 메타 패키지에 의존하고 <code>package: meta/meta.dart</code>를 가져옵니다.</p>
<h4 id="위치적-매개변수">위치적 매개변수</h4>
<p>함수 매개변수 세트를 <code>[]</code>로 감싸면 선택적 위치 매개변수로 표시됩니다.</p>
<pre><code class="language-dart">String say(String from, String msg, [String device]) {
  var result = &#39;$from says $msg&#39;;
  if (device != null) {
    result = &#39;$result with a $device&#39;;
  }
  return result;
}</code></pre>
<p>다음은 선택적 매개변수 없이 위 함수를 호출하는 예시입니다.</p>
<pre><code class="language-dart">assert(say(&#39;Bob&#39;, &#39;Howdy&#39;) == &#39;Bob says Howdy&#39;);</code></pre>
<p>다음은 세 번째 매개변수를 사용하여 위 함수를 호출하는 예시입니다.</p>
<pre><code class="language-dart">assert(say(&#39;Bob&#39;, &#39;Howdy&#39;, &#39;smoke signal&#39;) ==
    &#39;Bob says Howdy with a smoke signal&#39;);</code></pre>
<h4 id="매개변수의-기본-값">매개변수의 기본 값</h4>
<p>함수는 <code>=</code>를 사용하여 명시적 매개변수와 위치 매개변수 모두에 대한 기본값을 정의할 수 있습니다. 기본 값은 컴파일타임 상수여야 하며, 기본값이 제공되지 않으면 기본값은 <code>null</code>입니다.</p>
<p>다음은 명시적 매개변수에 대한 기본값을 설정하는 예시입니다.</p>
<pre><code class="language-dart">/// Sets the [bold] and [hidden] flags ...
void enableFlags({bool bold = false, bool hidden = false}) {...}

// bold will be true; hidden will be false.
enableFlags(bold: true);
 Deprecation note: Old code might use a colon (:) instead of = to set d</code></pre>
<blockquote>
<p>사용중단 참고: 이전 코드는 명시적 매개 변수의 기본값을 설정하기 위해 <code>=</code> 대신 콜론<code>:</code>을 사용할 수 있습니다. 그 이유는 원래 이름이 지정된 매개 변수에 대해<code>:</code>만 지원 되었기 때문입니다. 해당 지원은 더 이상 사용되지 않을 수 있으므로 <code>=</code>를 사용하여 기본값을 지정하는 것이 좋습니다.</p>
</blockquote>
<p>다음 예시는 위치 매개변수의 기본값을 설정하는 방법입니다.</p>
<pre><code class="language-dart">String say(String from, String msg,
    [String device = &#39;carrier pigeon&#39;, String mood]) {
  var result = &#39;$from says $msg&#39;;
  if (device != null) {
    result = &#39;$result with a $device&#39;;
  }
  if (mood != null) {
    result = &#39;$result (in a $mood mood)&#39;;
  }
  return result;
}

assert(say(&#39;Bob&#39;, &#39;Howdy&#39;) ==
    &#39;Bob says Howdy with a carrier pigeon&#39;);</code></pre>
<p>_List_이나 _Map_을 기본값으로 전달할 수도 있습니다. 다음 예제는 <code>list</code> 매개변수에 대한 기본 _List_과 <code>gifts</code> 매개 변수에 대한 기본 _Map_을 지정하는 함수 <code>doStuff()</code>를 정의합니다.</p>
<pre><code class="language-dart">void doStuff(
    {List&lt;int&gt; list = const [1, 2, 3],
    Map&lt;String, String&gt; gifts = const {
      &#39;first&#39;: &#39;paper&#39;,
      &#39;second&#39;: &#39;cotton&#39;,
      &#39;third&#39;: &#39;leather&#39;
    }}) {
  print(&#39;list:  $list&#39;);
  print(&#39;gifts: $gifts&#39;);
}</code></pre>
<h3 id="main-함수">main() 함수</h3>
<p>모든 앱에는 앱의 진입점 역할을하는 최상위 <code>main()</code> 함수가 있어야 합니다. <code>main()</code> 함수는 <code>void</code>를 반환하고 인수에 대한 선택적 <code>List&lt;String&gt;</code> 매개변수를 갖습니다.</p>
<p>다음은 웹 앱에 대한 <code>main()</code> 함수의 예시입니다.</p>
<pre><code class="language-dart">void main() {
  querySelector(&#39;#sample_text_id&#39;)
    ..text = &#39;Click me!&#39;
    ..onClick.listen(reverseText);
}</code></pre>
<blockquote>
<p>위 코드에서, <code>...</code>구문을 캐스케이드라고 합니다. 캐스케이드를 사용하면 단일 개체의 멤버에 대해 여러 작업을 수행할 수 있습니다.</p>
</blockquote>
<p>다음은 인수를 받는 명령줄 앱에 대한 <code>main()</code> 함수의 예시입니다.</p>
<pre><code class="language-dart">// Run the app like this: dart args.dart 1 test
void main(List&lt;String&gt; arguments) {
  print(arguments);

  assert(arguments.length == 2);
  assert(int.parse(arguments[0]) == 1);
  assert(arguments[1] == &#39;test&#39;);
}</code></pre>
<p><code>args</code> 라이브러리를 사용하여 명령줄 인수를 정의하고 구문분석 할 수 있습니다.</p>
<h3 id="객체로서의-함수-사용">객체로서의 함수 사용</h3>
<p>함수를 매개변수로 다른 함수에 전달할 수 있습니다. 예를 들면,</p>
<pre><code class="language-dart">void printElement(int element) {
  print(element);
}

var list = [1, 2, 3];

// Pass printElement as a parameter.
list.forEach(printElement);</code></pre>
<p>다음과 같이 변수에 함수를 할당할 수도 있습니다.</p>
<pre><code class="language-dart">var loudify = (msg) =&gt; &#39;!!! ${msg.toUpperCase()} !!!&#39;;
assert(loudify(&#39;hello&#39;) == &#39;!!! HELLO !!!&#39;);</code></pre>
<p>이 예시에서는 익명함수를 사용합니다. 다음 섹션에서 이에 대해 자세히 알아보십시오.</p>
<h3 id="익명함수">익명함수</h3>
<p>대부분의 함수는 <code>main()</code> 또는 <code>printElement()</code>와 같이 이름이 지정됩니다. 익명함수 또는 때때로 람다 또는 클로저라고하는 이름 없는 함수를 만들 수도 있습니다. 예를 들어 컬렉션에서 추가하거나 제거할 수 있도록 변수에 익명함수를 할당 할 수 있습니다.</p>
<p>익명 함수는 명시적 함수와 비슷합니다. 쉼표로 구분된 0개 이상의 매개변수와 괄호 사이의 선택적 유형 주석입니다.</p>
<p>다음 코드 블록에는 함수의 본문이 포함됩니다.</p>
<pre><code class="language-dart">([[Type] param1[, …]]) {
  codeBlock;
};</code></pre>
<p>다음 예제는 유형이 지정되지 않은 매개변수 인 <code>item</code>을 사용하여 익명함수를 정의합니다. _List_의 각 항목에 대해 호출되는 함수는 지정된 인덱스의 값을 포함하는 문자열을 출력합니다.</p>
<pre><code class="language-dart">var list = [&#39;apples&#39;, &#39;bananas&#39;, &#39;oranges&#39;];

list.forEach((item) {
  print(&#39;${list.indexOf(item)}: $item&#39;);
});

// list.forEach(
//    (item) =&gt; print(&#39;${list.indexOf(item)}: $item&#39;)
// ); 
// 함수에 명령문이 하나만 있는 경우 화살표 표기법을 사용하여 줄일 수 있습니다. 

// 출력 결과
// 0: apples
// 1: bananas
// 2: oranges</code></pre>
<h3 id="렉시컬-스코프">렉시컬 스코프</h3>
<p>Dart는 <del>Javascript 처럼</del> 렉시컬 스코프 언어입니다. 즉, 변수의 스코프가 코드 레이아웃에 따라 정적으로 결정됩니다. 변수가 범위 내에 있는지 확인하려면 &quot;중괄호를 바깥쪽으로&quot; 따라갈 수 있습니다.</p>
<p>다음은 각 스코프 수준에서 변수가 있는 중첩 함수의 예입니다.</p>
<pre><code class="language-dart">bool topLevel = true;

void main() {
  var insideMain = true;

  void myFunction() {
    var insideFunction = true;

    void nestedFunction() {
      var insideNestedFunction = true;

      assert(topLevel);
      assert(insideMain);
      assert(insideFunction);
      assert(insideNestedFunction);
    }
  }
}</code></pre>
<p><code>nestedFunction()</code>이 어떻게 모든 수준의 변수를 최상위 수준까지 사용할 수 있는지 확인하세요.</p>
<h3 id="렉시컬-클로저">렉시컬 클로저</h3>
<p>클로저는 함수가 원래 스코프 밖에서 사용되는 경우에도 어휘 범위의 변수에 액세스 할 수있는 함수 객체입니다.</p>
<p>함수는 주변 범위에 정의 된 변수를 통해 닫힐 수 있습니다. 다음 예제에서 <code>makeAdder()</code>는 변수 <code>addBy</code>를 캡처합니다. 반환 된 함수가 가는 곳마다 <code>addBy</code>를 기억합니다.</p>
<pre><code class="language-dart">/// Returns a function that adds [addBy] to the
/// function&#39;s argument.
Function makeAdder(int addBy) {
  return (int i) =&gt; addBy + i;
}

void main() {
  // Create a function that adds 2.
  var add2 = makeAdder(2);

  // Create a function that adds 4.
  var add4 = makeAdder(4);

  assert(add2(3) == 5);
  assert(add4(3) == 7);
}</code></pre>
<h3 id="동등성-테스트">동등성 테스트</h3>
<p>다음은 최상위 함수, 정적 메서드, 인스턴스 메서드가 같은지 테스트하는 예시입니다.</p>
<p>void foo() {} // A top-level function</p>
<p>class A {
  static void bar() {} // A static method
  void baz() {} // An instance method
}</p>
<pre><code class="language-dart">void main() {
  var x;

  // 최상위 함수 비교.
  x = foo;
  assert(foo == x);

  // 정적 메서드 비교
  x = A.bar;
  assert(A.bar == x);

  // 인스턴스 메서드 비교
  var v = A(); // Instance #1 of A
  var w = A(); // Instance #2 of A
  var y = w;
  x = w.baz;

  // 이러한 클로저는 동일한 인스턴스(#2)를 참조합니다.
  // 그래서 같음
  assert(y.baz == x);

  // 이러한 클로저는 다른 인스턴스를 참조합니다.
  // 그래서 다름
  assert(v.baz != w.baz);
}</code></pre>
<h3 id="반환-값">반환 값</h3>
<p>모든 함수는 값을 반환합니다. 반환 값을 지정하지 않으면 명령문은 <code>null</code>을 반환합니다. 함수 본문에 암시 적으로 추가됩니다.</p>
<pre><code class="language-dart">foo() {}

assert(foo() == null);</code></pre>
]]></description>
        </item>
        <item>
            <title><![CDATA[Dart Language Tour #2]]></title>
            <link>https://velog.io/@t0dd-kr/Dart-Language-Tour-2</link>
            <guid>https://velog.io/@t0dd-kr/Dart-Language-Tour-2</guid>
            <pubDate>Fri, 14 Aug 2020 08:43:18 GMT</pubDate>
            <description><![CDATA[<h2 id="변수">변수</h2>
<p>변수는 다음과 같이 선언합니다.</p>
<pre><code class="language-dart">var name = &#39;Bob&#39;; </code></pre>
<p><code>String</code> 타입의 값인 &#39;Bob&#39;을 name 변수에 넣어줍니다. 
타입이 <code>String</code> 이지만 충분히 유추가능하기 때문에, 명시해주지 않았습니다.
변수가 유동적이거나 하나의 타입에 국한되어있지 않다면, <code>Object</code>나 <code>dynamic</code> 타입으로 명시해주면 됩니다.</p>
<pre><code class="language-dart">dynamic name = &#39;Bob&#39;;</code></pre>
<p>아니면, <code>String</code> 타입으로 명시해줄 수도 있습니다.</p>
<pre><code class="language-dart">String name = &#39;Bob&#39;;</code></pre>
<h3 id="초기값-설정">초기값 설정</h3>
<p>Dart에서 초기값 설정이 안된 변수는 <code>null</code>의 초기값을 가지게 됩니다.</p>
<pre><code class="language-dart">int lineCount;
assert(lineCount == null); // development 모드에서만 실행되는 구문 (예외를 throw)</code></pre>
<h3 id="final_과-_const"><em>Final_과 _Const</em></h3>
<p>변수를 변경하지 않으려는 경우, var대신에 <code>final</code>이나 <code>const</code> 타입을 사용합니다.
<code>final</code> 타입의 변수는 초기값만 설정할 수 있습니다.
<code>const</code> 타입의 변수는 컴파일 타입 상수입니다. (상수 변수는 암시적으로 <code>final</code>입니다.)
최상위 <code>final</code> 또는 클래스 변수는 처음 사용될 때 초기화됩니다.</p>
<pre><code class="language-dart">final name = &#39;Bob&#39;; // 타입이 없어도 선언 가능
final String nickname = &#39;Bobby&#39;; 

name = &#39;Alice&#39;; // Error: a final variable can only be set once.
// final 변수는 한 번만 값을 가질 수 있음.</code></pre>
<p>컴파일 타임 상수가 될 변수에는 <code>const</code>를 사용합니다.
<code>const</code> 변수가 클래스 수준에 있으면 <code>static const</code>로 표기합니다.</p>
<blockquote>
<p>변수를 선언하는 경우 값을 숫자 또는 문자열 상수, <code>const</code> 변수 또는 숫자 상수에 대한 산술 연산의 결과와 같은 컴파일타임 상수로 설정합니다.</p>
</blockquote>
<pre><code class="language-dart">const bar = 1000000; // Unit of pressure (dynes/cm2)
const double atm = 1.01325 * bar; // Standard atmosphere</code></pre>
<p><code>const</code> 키워드는 상수 변수를 선언하기 위한 것이 아닙니다.
이를 이용하여 상수 값을 생성하고, 상수 값을 생성하는 생성자를 선언할 수도 있습니다.
모든 변수는 상수 값을 가질 수 있습니다.</p>
<pre><code class="language-dart">var foo = const [];
final bar = const [];

const baz = []; 
// 결국 []는 const [] 와 똑같기 때문에, 초기화 표현식에서 const를 생략함 (중복사용 방지)</code></pre>
<p><code>foo</code> 는 상수 값을 가졌었지만, <code>const</code> 타입의 변수가 아니기 때문에 값 변경이 가능합니다.</p>
<pre><code class="language-dart">foo = [1, 2, 3]; // Was const []</code></pre>
<p><code>baz</code> 는 <code>const</code> 타입 변수이기 때문에, 값 변경이 불가능합니다.</p>
<pre><code class="language-dart">baz = [42]; // Error: Constant variables can&#39;t be assigned a value.</code></pre>
<blockquote>
<p>Dart 2.5버전 부터 유형검사 및 캐스트 (<code>is</code> 와 <code>as</code>), <em>컬렉션 <code>if</code></em> 및 스프레드 연산자 (<code>...</code> 와 <code>...?</code>)를 사용하는 상수를 정의할 수 있습니다.</p>
</blockquote>
<pre><code class="language-dart">// Valid compile-time constants as of Dart 2.5.
const Object i = 3; // Where i is a const Object with an int value...
const list = [i as int]; // Use a typecast.
const map = {if (i is int) i: &quot;int&quot;}; // Use is and collection if.
const set = {if (list is List&lt;int&gt;) ...list}; // ...and a spread.</code></pre>
<h2 id="빌트-인-타입">빌트-인 타입</h2>
<p>Dart는 아래와 같은 타입들을 지원합니다.</p>
<ul>
<li>numbers</li>
<li>strings</li>
<li>booleans</li>
<li>lists (also known as arrays)</li>
<li>sets</li>
<li>maps</li>
<li>runes (for expressing Unicode characters in a string)</li>
<li>symbols</li>
</ul>
<p>상수를 사용하여 이러한 타입들의 개체를 초기화할 수 있습니다.
예를 들어 <code>&#39;this is a string&#39;</code>은 문자열 상수이고, <code>true</code> 는 부울 상수입니다.</p>
<p>Dart의 모든 변수는 객체 (클래스의 인스턴스)를 참조하기 때문에, 일반적으로 생성자를 사용하여 변수를 초기화할 수 있습니다. 일부 내장 타입에는 자체 생성자가 있습니다. </p>
<blockquote>
<p>예를 들어, Map() 생성자를 사용하여 Map 객체를 만들 수 있습니다.</p>
</blockquote>
<h3 id="numbers">Numbers</h3>
<p>Dart에서 숫자 타입은 두 가지로 나뉩니다.</p>
<h4 id="int"><em>int</em></h4>
<p>플랫폼에 따라 64비트 이하의 정수 값입니다. Dart VM에서 값은 $-2^{63}$ ~ $2^{63}-1$ 까지 가능합니다. Javascript로 컴파일된 Dart는 Javascript 숫자를 사용하며, $-2^{53}$ ~ $2^{53}-1$의 값을 허용합니다.</p>
<h4 id="double"><em>double</em></h4>
<p>IEEE 754 표준에 지정된 64비트 (배정 밀도) 부동 소수점 값을 허용합니다.</p>
<h4 id="num"><em>num</em></h4>
<p><code>int</code>와 <code>double</code> 모두 <code>num</code>의 하위 타입입니다. <code>num</code> 타입에는 <code>+</code>, <code>-</code>, <code>/</code>, <code>*</code> 같은 기본 연산자가 포함되며, 다른 메소드 중에서도 abs(), ceil(), floor()를 찾을 수 있습니다. (<code>&gt;&gt;</code>와 같은 비트 연산자는 <code>int</code> 클래스에 정의되어 있습니다.)</p>
<blockquote>
<p><code>num</code> 및 해당 하위 타입에 원하는 항목이 없는 경우 dart:math 라이브러리에 있을 수 있습니다.</p>
</blockquote>
<pre><code class="language-dart">var x = 1;
var hex = 0xDEADBEEF;

// 상수 int 예시</code></pre>
<pre><code class="language-dart">var y = 1.1;
var exponents = 1.42e5;

// 상수 double 예시</code></pre>
<blockquote>
<p>Dart 2.1 이후에서는 <code>double</code> 타입에 <code>int</code> 상수를 넣으면 자동으로 <code>double</code>로 변환됨.</p>
</blockquote>
<pre><code class="language-dart">double z = 1;</code></pre>
<p>아래와 같이 문자열을 숫자로, 숫자를 문자로 바꿀 수 있습니다.</p>
<pre><code class="language-dart">// String -&gt; int
var one = int.parse(&#39;1&#39;);
assert(one == 1);

// String -&gt; double
var onePointOne = double.parse(&#39;1.1&#39;);
assert(onePointOne == 1.1);

// int -&gt; String
String oneAsString = 1.toString();
assert(oneAsString == &#39;1&#39;);

// double -&gt; String
String piAsString = 3.14159.toStringAsFixed(2);
assert(piAsString == &#39;3.14&#39;);</code></pre>
<p><code>int</code> 타입은 기존 비트 Shift(<code>&lt;&lt;</code>, <code>&gt;&gt;</code>), And(<code>&amp;</code>), Or(<code>|</code>) 연산자를 지원합니다.</p>
<pre><code class="language-dart">assert((3 &lt;&lt; 1) == 6); // 0011 &lt;&lt; 1 == 0110
assert((3 &gt;&gt; 1) == 1); // 0011 &gt;&gt; 1 == 0001
assert((3 | 4) == 7); // 0011 | 0100 == 0111</code></pre>
<p>상수 숫자는 컴파일 타임 상수입니다. 피연산자가 숫자로 평가되는 컴파일 타임 상수로 인한 많은 산술식도 컴파일타임 상수입니다.</p>
<pre><code class="language-dart">const msPerSecond = 1000;
const secondsUntilRetry = 5;
const msUntilRetry = secondsUntilRetry * msPerSecond;</code></pre>
<h3 id="string">String</h3>
<p>Dart에서의 문자열은 일련의 UTF-16 코드 단위입니다. 작은 따옴표 또는 큰 따옴표를 사용하여 문자열을 만들 수 있습니다.</p>
<pre><code class="language-dart">var s1 = &#39;Single quotes work well for string literals.&#39;;
var s2 = &quot;Double quotes work just as well.&quot;;
var s3 = &#39;It\&#39;s easy to escape the string delimiter.&#39;;
var s4 = &quot;It&#39;s even easier to use the other delimiter.&quot;;</code></pre>
<p><code>${expr}</code> 를 사용하여 문자열 안에 표현식의 값을 넣을 수 있습니다.</p>
<blockquote>
<p>표현식이 식별자인 경우, <code>{}</code>를 건너뛸 수 있습니다. 객체에 해당하는 문자열을 얻기위해 Dart는 객체의 toString() 함수를 호출합니다.</p>
</blockquote>
<pre><code class="language-dart">var s = &#39;string interpolation&#39;;

assert(&#39;Dart has $s, which is very handy.&#39; ==
    &#39;Dart has string interpolation, &#39; +
        &#39;which is very handy.&#39;);
assert(&#39;That deserves all caps. &#39; +
        &#39;${s.toUpperCase()} is very handy!&#39; ==
    &#39;That deserves all caps. &#39; +
        &#39;STRING INTERPOLATION is very handy!&#39;);</code></pre>
<blockquote>
<p><code>==</code>연산자는 두 개체가 동일한 지 테스트합니다. 동일한 코드 단위 시퀀스를 포함하는 두 문자열은 동일합니다.</p>
</blockquote>
<p>인접한 문자열 리터럴 또는 <code>+</code> 연산자를 사용하여 문자열을 연결할 수 있습니다.</p>
<pre><code class="language-dart">var s1 = &#39;String &#39;
    &#39;concatenation&#39;
    &quot; works even over line breaks.&quot;;
assert(s1 ==
    &#39;String concatenation works even over &#39;
        &#39;line breaks.&#39;);

var s2 = &#39;The + operator &#39; + &#39;works, as well.&#39;;
assert(s2 == &#39;The + operator works, as well.&#39;);</code></pre>
<p>여러 줄의 문자열을 만드는 또 다른 방법으로, 작은 따옴표 또는 큰 따옴표로 삼중따옴표를 사용합니다.</p>
<pre><code class="language-dart">var s1 = &#39;&#39;&#39;
You can create
multi-line strings like this one.
&#39;&#39;&#39;;

var s2 = &quot;&quot;&quot;This is also a
multi-line string.&quot;&quot;&quot;;</code></pre>
<p><code>r</code>을 접두사로 붙여 _Raw String_을 만들 수 있습니다.</p>
<pre><code class="language-dart">var s = r&#39;In a raw string, not even \n gets special treatment.&#39;;</code></pre>
<p>문자열에 유니코드 문자를 표현하는 방법에 대한 자세한 내용은, <a href="https://dart.dev/guides/language/language-tour#characters">여기</a>를 참조하세요.</p>
<p>리터럴 문자열은 보간된 표현식이 <code>null</code> 또는 숫자, 문자열 또는 부울 값으로 평가되는 컴파일 타임 상수 </p>
<pre><code class="language-dart">// These work in a const string.
const aConstNum = 0;
const aConstBool = true;
const aConstString = &#39;a constant string&#39;;

// These do NOT work in a const string.
var aNum = 0;
var aBool = true;
var aString = &#39;a string&#39;;
const aConstList = [1, 2, 3];

const validConstString = &#39;$aConstNum $aConstBool $aConstString&#39;;
// const invalidConstString = &#39;$aNum $aBool $aString $aConstList&#39;;</code></pre>
<h3 id="boolean">Boolean</h3>
<p>Dart에는 부울값을 나타내기 위해 <code>true</code>, <code>false</code> 값만을 가지는 <code>bool</code> 타입이 있습니다. 두 값 모두 컴파일타임 상수입니다.</p>
<p>Dart의 유형 안정성은 if(nonbooleanValue) 또는 assert(nonbooleanValue)와 같은 코드를 사용할 수 없음을 의미합니다. 대신 아래와 같이 명시적으로 값을 확인하십시오.</p>
<pre><code class="language-dart">// 빈 문자열 검사.
var fullName = &#39;&#39;;
assert(fullName.isEmpty);

// 숫자 0 검사.
var hitPoints = 0;
assert(hitPoints &lt;= 0);

// null 인지 검사.
var unicorn;
assert(unicorn == null);

// 계산 결과 값이 NaN인지 검사.
var iMeantToDoThis = 0 / 0;
assert(iMeantToDoThis.isNaN);</code></pre>
<h3 id="list">List</h3>
<p>거의 모든 프로그래밍 언어에서 가장 일반적인 컬렉션은 배열 또는 정렬된 객체 그룹일 것입니다. Dart에서 배열은 <em>List</em> 객체입니다.</p>
<p>Dart <em>List</em> 리터럴은 Javascript <em>Array</em> 리터럴처럼 보입니다.</p>
<pre><code class="language-dart">var list = [1, 2, 3];
// Dart 배열 객체 선언</code></pre>
<blockquote>
<p>Dart는 배열에 <code>List&lt;int&gt;</code> 유형이 있다고 추론합니다. 이 배열에 정수가 아닌 개체를 추가하려고하면 분석기 또는 런타임에서 오류가 발생합니다. 자세한 내용은 <a href="https://dart.dev/guides/language/type-system#type-inference">유형추론</a>을 참조하세요.</p>
</blockquote>
<p>배열은 0부터 시작하는 인덱싱을 사용합니다. <code>0</code>은 첫 요소의 인덱스이고, <code>list.length - 1</code>은 마지막 요소의 인덱스입니다. Javascript에서와 마찬가지로, 배열의 길이를 가져오고 목록 요소를 참조할 수 있습니다.</p>
<pre><code class="language-dart">var list = [1, 2, 3];
assert(list.length == 3);
assert(list[1] == 2);

list[1] = 1;
assert(list[1] == 1);</code></pre>
<p>컴파일타임 상수인 배열을 만들려면 배열 리터럴 앞에 const를 추가합니다.</p>
<pre><code class="language-dart">var constantList = const [1, 2, 3];
// constantList[1] = 1; // Error! 컴파일타임 상수배열의 요소를 변경할 수 없음.</code></pre>
<p>Dart 2.3은 배열에 여러 요소를 삽입하는 간결한 방법을 제공하는 스프레드 연산자 <code>...</code>와 <code>null</code> 인식 확산 연산자 <code>...?</code>를 도입했습니다.</p>
<p>예를 들어 스프레드 연산자 <code>...</code>를 사용하여 목록의 모든 요소를 다른 목록에 삽입 할 수 있습니다.</p>
<pre><code class="language-dart">var list = [1, 2, 3];
var list2 = [0, ...list];
assert(list2.length == 4);</code></pre>
<p>스프레드 연산자 오른쪽에 있는 식이 <code>null</code>일 수 있는 경우, <code>null</code>인식 스프레드 연산자 <code>...?</code> 를 사용하여 예외를 피할 수 있습니다.</p>
<pre><code class="language-dart">var list;
var list2 = [0, ...?list];
assert(list2.length == 1);</code></pre>
<p>스프레드 연산자 사용에 대한 자세한 내용과 예는 스프레드 연산자 제안을 참조하세요.</p>
<p>Dart 2.3은 또한 조건부 <em>if</em> 및 반복 <em>for_을 사용하여 배열 구축하는 데 사용할 수 있는 _collection if</em> 및 _collection for_를 도입했습니다.</p>
<p>다음은 3개 또는 4개의 항목이있는 목록을 만드는 경우 배열을 사용하는 예시입니다.</p>
<pre><code class="language-dart">var nav = [
  &#39;Home&#39;,
  &#39;Furniture&#39;,
  &#39;Plants&#39;,
  if (promoActive) &#39;Outlet&#39;
];</code></pre>
<p>다음은 배열 사용하여 목록의 항목을 다른 배열에 추가하기 전에 변경하는 예시입니다.</p>
<pre><code class="language-dart">var listOfInts = [1, 2, 3];
var listOfStrings = [
  &#39;#0&#39;,
  for (var i in listOfInts) &#39;#$i&#39;
];
assert(listOfStrings[1] == &#39;#1&#39;);</code></pre>
<p>배열 사용에 대한 자세한 내용과 예제는 <a href="https://github.com/dart-lang/language/blob/master/accepted/2.3/control-flow-collections/feature-specification.md">제어 흐름 컬렉션 제안</a>을 참조하세요.</p>
<p>배열 유형에는 배열을 조작하는 여러 가지 편리한 방법이 있습니다. 배열에 대한 자세한 내용은 <a href="https://dart.dev/guides/language/language-tour#generics">제네릭</a> 및 <a href="https://dart.dev/guides/libraries/library-tour#collections">컬렉션</a>을 참조하세요.</p>
<h3 id="sets">Sets</h3>
<p>Dart의 <em>Set_는 순서가 지정되지 않은 고유한 아이템 모음입니다. 집합에 대한 Dart 지원은 _Set</em> 리터럴과 <em>Set</em> 타입에 의해 제공됩니다.</p>
<blockquote>
<p><em>Set</em> 유형은 항상 Dart의 핵심 부분 이었지만 <em>Set</em> 리터럴은 Dart 2.2에서 도입되었습니다.</p>
</blockquote>
<p>간단한 _Set_의 예시입니다.</p>
<pre><code class="language-dart">var halogens = {&#39;fluorine&#39;, &#39;chlorine&#39;, &#39;bromine&#39;, &#39;iodine&#39;, &#39;astatine&#39;};</code></pre>
<blockquote>
<p>Dart는 <code>halogens</code>의 타입이 <code>Set&lt;String&gt;</code>이라고 추론합니다. _Set_에 잘못된 타입의 값을 추가하려고하면 분석기 또는 런타임에서 오류가 발생합니다. 자세한 내용은 <a href="https://dart.dev/guides/language/type-system#type-inference">유형 추론</a>을 참조하세요.</p>
</blockquote>
<p>빈 <em>Set_을 만들려면 타입 인수 앞에 {}를 사용하거나 {}를 _Set</em> 타입의 변수에 할당합니다.</p>
<pre><code class="language-dart">var names = &lt;String&gt;{};
// Set&lt;String&gt; names = {}; // 이렇게 써도 됩니다.
// var names = {}; // Map을 만듭니다.</code></pre>
<blockquote>
<p><strong><em>Set</em> 또는 <em>Map</em>?</strong> 
<em>Map</em> 리터럴의 구문은 <em>Set</em> 리터럴의 구문과 유사합니다. <em>Map</em> 리터럴이 먼저 왔기 때문에 {}는 기본적으로 <em>Map</em> 유형입니다. {}의 타입 주석 또는 할당 된 변수를 잊어 버린 경우 Dart는 Map &lt;dynamic, dynamic&gt; 타입의 개체를 만듭니다.</p>
</blockquote>
<p><code>add ()</code> 또는 <code>addAll ()</code> 메서드를 사용하여 기존 _Set_에 항목을 추가합니다.</p>
<pre><code class="language-dart">var elements = &lt;String&gt;{};
elements.add(&#39;fluorine&#39;);
elements.addAll(halogens);</code></pre>
<p><code>.length</code>를 사용하여 _Set_의 항목 수를 가져옵니다.</p>
<pre><code class="language-dart">var elements = &lt;String&gt;{};
elements.add(&#39;fluorine&#39;);
elements.addAll(halogens);
assert(elements.length == 5);</code></pre>
<p>컴파일타임 상수 인 <em>Set_을 만들려면 _Set</em> 리터럴 앞에 <code>const</code>를 추가합니다.</p>
<pre><code class="language-dart">final constantSet = const {
  &#39;fluorine&#39;,
  &#39;chlorine&#39;,
  &#39;bromine&#39;,
  &#39;iodine&#39;,
  &#39;astatine&#39;,
};
// constantSet.add(&#39;helium&#39;); // Uncommenting this causes an error.</code></pre>
<p>Dart 2.3부터 <em>Set_는 _List_과 마찬가지로 스프레드 연산자 (<code>...</code> 및 <code>...?</code>)와 _collection if</em> 및 <em>collection for_를 지원합니다. 자세한 내용은 [_List</em> 스프레드 연산자](<a href="https://dart.dev/guides/language/language-tour#spread-operator">https://dart.dev/guides/language/language-tour#spread-operator</a>) 및 <a href="https://dart.dev/guides/language/language-tour#collection-operators"><em>List</em> 수집 연산자</a> 토론을 참조하세요.</p>
<p>_Set_에 대한 자세한 내용은 <a href="https://dart.dev/guides/language/language-tour#generics">제네릭</a> 및 <a href="https://dart.dev/guides/libraries/library-tour#sets"><em>Set</em></a>을 참조하십시오.</p>
<h3 id="maps">Maps</h3>
<p>일반적으로 <em>Map_은 키와 값으로 이루어진 객체입니다. 키와 값은 모든 유형의 객체가 될 수 있습니다. 각 키는 한 번만 발생하지만 동일한 값을 여러 번 사용할 수 있습니다. _Map_에 대한 Dart 지원은 _Map</em> 리터럴과 <em>Map</em> 타입에 의해 제공됩니다.</p>
<p>다음은 <em>Map</em> 리터럴을 사용하여 만든 몇 가지 간단한 Dart _Map_입니다.</p>
<pre><code class="language-dart">var gifts = {
  // Key:    Value
  &#39;first&#39;: &#39;partridge&#39;,
  &#39;second&#39;: &#39;turtledoves&#39;,
  &#39;fifth&#39;: &#39;golden rings&#39;
};

var nobleGases = {
  2: &#39;helium&#39;,
  10: &#39;neon&#39;,
  18: &#39;argon&#39;,
};

//Javascript Object와 유사함.</code></pre>
<blockquote>
<p>Dart는 <code>gifts</code>의 타입이 <code>Map &lt;String, String&gt;</code>이고 <code>nobleGases</code>의 유형이 <code>Map &lt;int, String&gt;</code>이라고 추론합니다. 잘못된 타입의 값을 _Map_에 추가하려고하면 분석기 또는 런타임에서 오류가 발생합니다. 자세한 내용은 <a href="https://dart.dev/guides/language/type-system#type-inference">유형 추론</a>을 참조하세요.</p>
</blockquote>
<p><em>Map</em> 생성자를 사용하여 동일한 객체를 만들 수 있습니다.</p>
<pre><code class="language-dart">var gifts = Map();
gifts[&#39;first&#39;] = &#39;partridge&#39;;
gifts[&#39;second&#39;] = &#39;turtledoves&#39;;
gifts[&#39;fifth&#39;] = &#39;golden rings&#39;;

var nobleGases = Map();
nobleGases[2] = &#39;helium&#39;;
nobleGases[10] = &#39;neon&#39;;
nobleGases[18] = &#39;argon&#39;;</code></pre>
<blockquote>
<p><code>Map ()</code> 대신 <code>new Map ()</code>이 표시 될 것으로 예상 할 수 있습니다. Dart 2에서 <code>new</code> 키워드는 선택 사항입니다. 자세한 내용은 <a href="https://dart.dev/guides/language/language-tour#using-constructors">생성자 사용</a>을 참조하세요.</p>
</blockquote>
<p>Javascript에서와 같이 기존 _Map_에 새로운 키-값 쌍을 추가할 수 있습니다.</p>
<pre><code class="language-dart">var gifts = {&#39;first&#39;: &#39;partridge&#39;};
gifts[&#39;fourth&#39;] = &#39;calling birds&#39;; // Add a key-value pair</code></pre>
<p>JavaScript 에서와 같은 방식으로 _Map_에서 값을 검색합니다.</p>
<pre><code class="language-dart">var gifts = {&#39;first&#39;: &#39;partridge&#39;};
assert(gifts[&#39;first&#39;] == &#39;partridge&#39;);</code></pre>
<p>_Map_에 없는 키를 찾으면 <code>null</code>이 반환됩니다.</p>
<pre><code class="language-dart">var gifts = {&#39;first&#39;: &#39;partridge&#39;};
assert(gifts[&#39;fifth&#39;] == null);</code></pre>
<p><code>.length</code>를 사용하여 _Map_에서 키-값 쌍의 수를 가져옵니다</p>
<pre><code class="language-dart">var gifts = {&#39;first&#39;: &#39;partridge&#39;};
gifts[&#39;fourth&#39;] = &#39;calling birds&#39;;
assert(gifts.length == 2);</code></pre>
<p>컴파일타임 상수 인 <em>Map_을 만들려면 _Map</em> 리터럴 앞에 <code>const</code>를 추가합니다.</p>
<pre><code class="language-dart">final constantMap = const {
  2: &#39;helium&#39;,
  10: &#39;neon&#39;,
  18: &#39;argon&#39;,
};

// constantMap[2] = &#39;Helium&#39;; // Uncommenting this causes an error.</code></pre>
<p>Dart 2.3부터 <em>Map_은 _List</em> 마찬가지로 스프레드 연산자 (<code>...</code> 및 <code>...?</code>) 및 수집을 지원합니다. 자세한 내용과 예시는 <a href="https://github.com/dart-lang/language/blob/master/accepted/2.3/spread-collections/feature-specification.md">스프레드 운영자 제안</a> 및 <a href="https://github.com/dart-lang/language/blob/master/accepted/2.3/control-flow-collections/feature-specification.md">제어 흐름 수집 제안</a>을 참조하십시오.</p>
<p>_Map_에 대한 자세한 내용은 <a href="https://dart.dev/guides/language/language-tour#generics">제네릭</a> 및 <a href="https://dart.dev/guides/libraries/library-tour#maps"><em>Map</em></a>을 참조하십시오.</p>
<h3 id="runes-and-grpheme-clusters">Runes and grpheme clusters</h3>
<p>Dart에서 _Rune_은 문자열의 유니코드 코드포인트를 노출합니다. Dart 2.6부터는 문자 패키지를 사용하여 유니 코드 (확장) 자소 클러스터라고도하는 사용자 인식 문자를 보거나 조작합니다.</p>
<p>유니코드는 전 세계의 모든 문자 체계에서 사용되는 각 문자, 숫자 및 기호에 대해 고유 한 숫자 값을 정의합니다. Dart 문자열은 일련의 UTF-16 코드 단위이므로 문자열 내에서 유니코드 코드포인트를 표현하려면 특수 구문이 필요합니다. 유니코드 코드포인트를 표현하는 일반적인 방법은 \uXXXX입니다. 여기서 XXXX는 4 자리 16진수 값입니다. 예를 들어 하트 (♥)는 \u2665입니다. 4자리 이하의 16진수를 지정하려면 값을 중괄호 안에 넣으십시오. 예를 들어 웃는 이모티콘 (😆)은 \u{1f606}입니다.</p>
<p>개별 유니 코드 문자를 읽거나 써야하는 경우 characters 패키지에 의해 String에 정의 된 문자 getter를 사용하십시오. 반환 된 Characters 객체는 문자 소 클러스터의 시퀀스로서의 문자열입니다. 다음은 characters API 사용의 예입니다.</p>
<pre><code class="language-dart">import &#39;package:characters/characters.dart&#39;;
...
var hi = &#39;Hi 🇩🇰&#39;;
print(hi);
print(&#39;The end of the string: ${hi.substring(hi.length - 1)}&#39;);
print(&#39;The last character: ${hi.characters.last}\n&#39;);</code></pre>
<p>환경에 따라 출력은 다음과 같습니다.
<img src="https://images.velog.io/images/t0dd-kr/post/20c773a5-eceb-422d-b93d-826972b7e5dd/image.png" alt=""></p>
<p>문자 패키지를 사용하여 문자열을 조작하는 방법에 대한 자세한 내용은 문자 패키지의 <a href="https://pub.dev/packages/characters#-example-tab-">예제</a> 및 <a href="https://pub.dev/documentation/characters">API 참조</a>를 참조하십시오.</p>
<h3 id="symbols">Symbols</h3>
<p><em>Symbol</em> 객체는 Dart 프로그램에서 선언 된 연산자 또는 식별자를 나타냅니다. 기호를 사용할 필요는 없지만 이름으로 식별자를 참조하는 API에는 매우 유용합니다. 축소화는 식별자 이름을 변경하지만 식별자 기호는 변경하지 않기 때문입니다.</p>
<p>식별자에 대한 기호를 얻으려면 기호 리터럴을 사용하십시오. 기호 리터럴은 # 뒤에 식별자가옵니다.</p>
<pre><code class="language-dart">#radix
#bar
// Symbol 리터럴은 컴파일 타임 상수입니다.</code></pre>
]]></description>
        </item>
        <item>
            <title><![CDATA[Dart Language Tour #1]]></title>
            <link>https://velog.io/@t0dd-kr/Dart-Language-Tour-1</link>
            <guid>https://velog.io/@t0dd-kr/Dart-Language-Tour-1</guid>
            <pubDate>Fri, 14 Aug 2020 08:19:04 GMT</pubDate>
            <description><![CDATA[<p><a href="https://dart.dev/guides/language/language-tour%EB%A5%BC">https://dart.dev/guides/language/language-tour를</a> 요약/번역하며 Dart를 공부해보자.</p>
<hr>
<h3 id="간단한-다트-프로그램">간단한 다트 프로그램</h3>
<pre><code class="language-dart">// 함수의 정의
printInteger(int aNumber) {
  print(&#39;The number is $aNumber.&#39;); 
  // print(~)로 콘솔에 출력
  // 문자열 안에 &quot;$변수명&quot;으로 변수를 출력가능
}

// dart의 메인 함수
main() {
  var number = 42; 
  // 변수 선언/초기화
  // dart에는 JS와 같이 var가 있음
  printInteger(number); // 함수 호출
}</code></pre>
<h3 id="중요-개념">중요 개념</h3>
<blockquote>
<p>Dart에 대해 알아야할 개념을 간단히 살펴보자</p>
</blockquote>
<ul>
<li>변수에 넣을 수 있는 모든 것은 _객체_이고, 모든 객체는 _클래스_의 인스턴스이다. 심지어 숫자, 함수, null도 객체이다. 모든 객체들은 <code>Object</code>클래스를 상속한다.</li>
<li>Dart는 타입이 강력히 정해져있지만, 타입 명시는 Dart는 유형을 추론할 수 있을 땐 선택사항입니다. 예상되는 유형이 없다고 명시적으로 말하려면 특수 유형 <code>dynamic</code>을 사용하십시오.</li>
<li>Dart는 <code>List&lt;int&gt;</code>또는 <code>List&lt;dynamic&gt;</code>과 같은 관용적인 타입을 지원합니다.</li>
<li>Dart는 최상위 함수(<code>main()</code>)과 클래스 또는 객체에 연결된 함수(각각 정적 및 인스턴스 메서드)를 지원합니다. 함수 내에서 함수 (중첩 또는 로컬 함수)를 만들 수도 있습니다.</li>
<li>마찬가지로 Dart는 최상위 변수와 클래스 또는 객체에 연결된 변수 (정적 및 인스턴스 변수)를 지원합니다. 인스턴스 변수는 <em>필드</em> 또는 _속성_이라고도 합니다.</li>
<li>Java와 달리 Dart에는 <code>public</code>,<code>protected</code>, <code>private</code> 키워드가 없습니다. 식별자가 밑줄(_)로 시작하면 라이브러리에 비공개입니다.</li>
<li>식별자는 문자 또는 밑줄(_)로 시작하고 그 뒤에 해당 문자와 숫자의 조합이 올 수 있습니다.</li>
<li>Dart에는 표현식(런타임 값이 있음)과 구문(없음)이 모두 있습니다. <blockquote>
<p>이는 JS에서의 함수표현식과 함수선언식과 비슷합니다.
예를 들어, <code>condition ? exprTrue : exprFalse</code>의 값은 <code>exprTrue</code> 또는 <code>exprFalse</code>입니다. 런타임 값이 없는 if-else문과 비교하십시오. </p>
</blockquote>
</li>
<li>구문은 종종 하나 이상의 표현식을 포함하지만, 표현식은 구문을 포함할 수 없습니다.</li>
<li>Dart 도구는 _경고_와 _오류_의 두가지 문제를 보고할 수 있습니다. _경고_는 코드가 작동하지 않을 수도 잇음을 나타내는 것일 뿐, 프로그램 실행을 방해하지 않습니다. _오류_는 컴파일 타임 또는 런타임일 수 있습니다. 컴파일 타임 오류는 코드가 전혀 실행되지 않습니다. 런타임 오류는 코드가 실행되는 동안 예외가 발생합니다.</li>
</ul>
<h3 id="키워드">키워드</h3>
<p>참조 : <a href="https://dart.dev/guides/language/language-tour#keywords">https://dart.dev/guides/language/language-tour#keywords</a></p>
]]></description>
        </item>
    </channel>
</rss>