dart 문법

다트 문법은 main() 함수가 진입점(entry point)이다.

void main() {
    print("Hello, World!");
}

목차

  1. 기본 문법
  2. 함수
  3. 분기와 반복



1. 기본 문법

// 한 줄 주석

/**
* 여러 줄 주석
*
**/

/// 문서 주석 (메서드나 클래스 위에 작성하면 문서를 자동으로 생성해줌)

변수

dart는 다음과 같은 기본 타입을 제공한다.

  • int : 정수
    int i = 10;
    num i2 = 10; // int는 num으로 표현 가능하다.
    
  • double : 실수
    double d = 10.00;
    num d2 = 10.00; // double 또한 num으로 표현 가능하다.
    
  • String : 문자열
    String name;
    // 작은 따옴표, 큰 따옴표 둘 다 사용 가능함
    name = '임기원';
    name = "임기원";
    
  • bool : 참 또는 거짓
    bool b = true;
    bool bw = i < 10;
    bool b3 = s.isEmpty;
    

타입 추론

dart는 var, dynamic 키워드를 통해 타입 추론을 지원한다.

  • var최초 할당된 값에 따라 타입이 정해진다.
    (선언만 하고 나중에 초기화를 진행하면 dynamic 타입처럼 타입을 변동시켜도 에러가 나지 않는다.)

    var i = 10; // int 타입
    var d = 10.0; // double 타입
    var s = 'hello'; // 문자열 타입
    var b = true; // 불리언 타입
    
    var n; // 초기화를 안한다면?
    var n = 1; // int도 들어가고
    var n = '안녕?'; // int -> String도 된다. (dynamic처럼 동작함)
    
  • dynamic var와 달리 할당된 타입에 관계없이 타입을 변경할 수 있다.
    dart를 JS처럼 사용하고 싶다면 dynamic을 쓰면 된다!

    dynamic name = '임기원';
    name = 1;
    

상수 final, const

Java의 final, JavaScript의 const에 대응한다고 생각하면 된다.

final String name = '임기원';
final name = '임기원'; // 타입을 생략하여 짧게 작성할 수도 있다.

산술 연산자

  • + : 더하기
  • - : 빼기
  • * : 곱하기
  • / : 나누기 (double 타입 반환)
  • ~/ : 몫 (int 타입 반환)
  • % : 나머지 (int 타입 반환)

assert() 함수는 계산 결과가 참인지 검사한다.

assert(2 + 3 == 5); // true
assert('hello' + ' world' == 'hello world'); // true

증감 연산자

  • 후위 연산 : [식]++, [식]--
  • 전위 연산 : ++[식], --[식]

비교 연산자

  • == : 같다
  • != : 다르다
  • > : 더 크다
  • < : 더 작다
  • >= : 크거나 같다
  • <= : 작거나 같다.
assert(2 == 2);
assert(2 != 3);
assert(3 > 2);
// ...

논리 연산자

  • && : and
  • || : or
  • == : equal
  • ! : not
  • != : not equal

타입 검사 (is, is! 키워드)

  • is : 같은 타입이면 true
  • is! : 다른 타입이면 true
int a = 10;
if (a is int) {
    print('정수');
}

String text = 'hello';
if (text is! int) {
    print('숫자가 아님');
}

형변환 (as 키워드)

형변환(타입 캐스팅)에는 as 키워드를 사용한다. 다른 타입끼리는 변환이 안 되고 더 상위 개념으로 변환할 수 있다.

var c = 30.5;
int d = c as int; // c는 double타입으로 추론 -> int는 double의 상위가 아니기에 변환 불가

var d = 30.5;
num n = d; // as num; 생략 가능

2. 함수

함수의 기본 형태

int f(int x, int y) {
    return x + y + 10;
}

void greeting(String greet) {
    print('hello $greet');
}


// 반환타입 역시 타입 추론에 의해 생략할 수 있다.
f(int x, int y) {
    return x + y + 10;
}

greeting(String greet) {
    print('hello $greet');
}

함수와 메서드

클래스 밖에 작성하는 함수를 최상위 함수라고 한다.
최상위 함수는 어디에서나 호출할 수 있으며,
클래스 내부함수는 메서드라고 부르기 때문에 사실상 대부분의 함수는 최상위 함수라고 볼 수 있다.

// 최상위 함수
bool isEven(int number) {
    return number & 2 == 0;
}

void main() {
    print(isEven(10));
}

class MyClass {
    // static 키워드로 정적 메서드를 만들어주면 최상위 함수처럼 사용 가능하다.
    static bool isEven(int number) {
        return number % 2 == 0;
    }

    // ...생략...
    print(MyClass.isEven(10));
}

익명 함수

(number) { // 익명 함수 역시 타입 추론 가능
    return number % 2 == 0;
}

람다식

([인수명]) -> [동작 또는 반환값]

(number) => number % 2 == 0;

선택 매개변수

{}로 감싼 매개변수는 선택적으로 사용할 수 있다.

void something(String name, {int age}) {
    // ...
}

void main() {
    something(name: '홍길동', age: 10);
    something(name: '홍길동');
    something(age: 10); // 에러
    something(); // 에러
}

또한 선택 매개변수는 기본값을 지정할 수 있다.

void something(String name, {int age = 10}) {
    // ...
}

3. 분기와 반복

if else

String text = 'hello';

if (text is int) {
    print('정수');
} else if (text is double) {
    print('실수');
} else {
    print('정수도 실수도 아님');
}

삼항 연산자

// [조건] ? [참일 때] : [거짓일 때]
var todo = isRainy ? '빨래를 하지 않는다' : '빨래를 한다';

switch cast

dart의 스위치문은 열거(enum)타입과 함께 사용할 경우,
모든 케이스를 전부 검사해야 하는 강제성이 생긴다.
사람의 실수를 방지하는 이런 기능이 있어서 특수한 경우에는 if 문 보다 유용하다.

enum Status { Uninitialized, Authenticated, Authenticating, Unauthenticated }

void main() {
    var status = Status.Authenticated;
    switch (status) {
        case Status.Authenticated:
            print('인증됨');
            break;
        case Status.Authenticating:
            print('인증 처리 중');
            break;
        case Status.Unauthenticated:
            print('미인증');
            break;
        case Status.Uninitialized:
            print('초기화됨');
            break;
    }
}

for

var items = ['짜장', '라면', '볶음밥'];

for (var i = 0; i < items.length; i++) {
    print(items[i]);
}

4. 객체 지향 프로그래밍

클래스 (Class)

class Person {
    String name;
    int age;

    void addOneYear() {
        age++;
    }
}

// ...생략...

var person = Person(); // new 키워드 생략 가능
person.age = 10;
person.addOneYear();
print(person.age); // 11

접근 지정자

변수명 앞에 _ 기호를 붙이면 해당 클래스가 정의되지 않은 외부에서 접근이 불가능해진다.
(Java의 private 역할)

// person.dart 파일
class Person {
    String name;
    int _age;
}
// main.dart 파일
import 'person.dart';
// ...생략...
var person = Person();
person._age = 10; // 에러!!! 접근 불가

생성자

기본 생성자는 클래스명과 같은 이름의 메서드이다.
사용자 정의 생성자를 추가하면 기본 생성자를 사용할 수 없게 되지만,
선택 매개변수를 사용하면 기본생성자도 호출 가능하다.
(정확히는 기본생성자를 호출 가능한게 아닌 선택매개변수에 null을 대입한 생성자가 호출되는 것이다.)

class Person {
    String name;
    int _age;

    Person({this.name, this._age}); // 생성자
}

// ...생략...
var person = Person();
var person2 = Person(name: '임기원', _age: 28);

getter, setter

_를 붙이는 private 변수의 경우, 클래스 외부에서 접근하려면 getter, setter를 사용해야 한다.

// person.dart
class Rectangle {
    num left, top, width, height;

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

    // getter : [리턴타입] [get] [함수이름] => [리턴값]
    num get right => left + width;
    // setter : [set] [함수이름]([매개변수]) => [함수로직]
    set right(num value) => left = value - width;

    num get bottom => top + height;
    set bottom(num value) => top = value - height;
}

상속

class Hero {
    String name = '영웅';

    void run() {}
}

class SuperHero extends Hero {

    
    void run() {
        super.run(); // 부모의 run()을 실행
        this.fly(); // 추가로 fly()도 실행
    }

    void fly() {}
}

void main() {
    var hero = SuperHero();
    hero.run(); // ok
    hero.fly(); // ok
    print(hero.name); // 영웅
}

추상 클래스

추상 클래스는 추상 메서드를 포함하는 메서드다.
추상 메서드는 선언만 되고 정의가 없는 메서드다.
다중상속 또한 지원한다.

abstract class Flyable {
    void fly();
}

class Bat implements Monster, Flyable {
    
    void attack() {
        print('할퀴기!');
        
    
    void fly() {
        print('펄럭펄럭');
    }
}

믹스인

with 키워드를 사용하여 상속하지 않고 다른 클래스의 기능을 가져오거나 오버라이드할 수 있다.

class Goblin implements Monster {
    
    void attack() {
        print('고블린 어택');
    }
}

class DarkGoblin extends Goblin with Hero {

}

열거 타입

상수를 정의하는 특수한 형태의 클래스이다. 열거 타입을 switch문에 사용하면 모든 상수를 전부 검사해야 한다.

enum Status { login, logout }
var authStatus = Status.logout;

switch(authStatus) {
    case Status.login:
        print('로그인');
        break;
    case Status.logout:     // 없으면 에러
        print('로그아웃');
        break;
}
Last Updated: