본문 바로가기

DART

[DART] 기본 문법 익히기

Dart는 자바스크립트와 매우 유사하다.

간단하게 Dart 문법에 대해서 알아보자.

 

void main() {
  // 실행되는 코드...
}
기본적으로 main() {} 내부에서 코드를 작성한다.

 

1. console 출력하기

void main() {
  print('Hello world');
}

 

2. 변수 Variable

void main() {
  var name = '다트 언어';
  print(name);
}

변수를 var로 선언할 경우 모든 타입의 초깃값을 할당할 수 있다. (string, integer, double, boolean ...)
그래서 var 대신에 String, int, double, bool 등의 정확한 타입을 지정해서 변수를 만드는 걸 권장한다.
⭐ var로 변수 선언 후, 재 할당할 수 있는데, 같은 타입의 값만 재 할당 할 수 있다.
name이라는 변수는 초깃값으로 String 타입이 들어가 있기 때문에, String 값만 재 할당 할 수 있게 된다.
int나 bool 등 다른 타입의 값을 재 할당하면 에러가 발생한다.

String 타입의 name 변수에 int 타입의 숫자를 재 할당 하려고 하면 에러가 발생 한다.

 

void main() {
  var name = '다트 언어';
  var name2 = '플러터';

  print(name + ' ' + name2);
  print('${name} 는 구글에서 만든 $name2 에 많이 쓰인다.');
}

변수를 콘솔로 출력하는 방법에는 몇 가지가 있는데
그냥 변수명을 써서 출력하기도 하고, $변수명을 사용해서 문자열과 섞어서 출력할 수도 있다.
자바스크립트의 템플릿 리터럴과 비슷하긴 하지만 변수명을 중괄호{}로 감싸거나 감싸지 않을 수도 있고,
백틱(`)이 아닌 따옴표(')로 감싸야 한다.

 

3. 정수 타입 Integer

void main() {
  int number = 1;
  int number2 = -10;
  int sum = number + number2;
  print(sum); // -9
}

 

4. 실수 타입 Dobule

void main() {
  double number = 2.5;
  double number2 = 0.5;
}

 

5. 논리 타입 Boolean

void main() {
  bool isTrue = true;
  bool isFalse = false;
}

 

6. 문자열 타입 String

void main() {
  String domain = '구글';
}

 

7. 동적 타입 Dynamic

void main() {
  dynamic name = '다트'; // type : String
  dynamic number = 3; // type : int

  // 재 할당
  name = false; // type : String => bool
  number2 = 1.5; // type : int => double
}
⭐ var로 변수 선언할 때와 다르게 dynamic으로 변수를 선언할 경우 다른 타입의 값을 재 할당할 수 있다.
var보다 훨씬 유연하다고 볼 수 있다.

 

8. 변수의 타입 출력

void main() {
  String name = '다트';
  Int number = 7;
  double number2 = 1.2;
  bool isTrue = true;

  print(name.runtimeType); // String
  print(number.runtimeType); // int
  print(number2.runtimeType); // dobule
  print(isTrue.runtimeType); // bool
}
변수명.runtimeType을 사용해서 변수의 타입을 출력해 볼 수 있다.

 

9. Nullable & Non-nullable

void main() {
  // nullable : null이 될 수 있다.
  // non-nullable : null이 될 수 없다.
  String name = '다트';
  name = null; // 에러 발생.

  String? name2 = '플러터';
  name2 = null; // null 재 할당 가능.
}
변수 선언 타입 뒤에 물음표(?)를 붙여서 nullable 타입의 변수로 만들면 null을 할당할 수 있게 된다.
⭐ 기본적으로 초깃값에 특정 타입의 값을 할당하거나, 타입을 지정해서 변수를 선언한 경우엔 non-nullable 타입이다.

 

⭐ var에서의 Nullable & Non-nullable

void main() {
  var name = '널 아님';
  name = null; // 에러 발생.

  var nullTest = null; // 초깃값 null 할당

  // 여러 타입의 값 재 할당 가능.
  nullTest = '널 아님';
  nullTest = 1;
  nullTest = false;
}

 

⭐ dynamic에서의 Nullable & Non-nullable

void main() {
  dynamic nullTest = '널 아님';

  nullTest = null;
  nullTest = 1;
  nullTest = true;
}
dynamic은 초깃값과 상관없이 모든 타입null 재 할당이 가능하다. (가장 유연한 변수 선언문)

 

Not null

void main() {
  var name = '다트';
  print(name!);
}
변수명 뒤에 느낌표(!)를 붙여서 '해당 변수는 null이 아니다'라고 강조할 수도 있다.

 

10. Final & Const

void main() {
  final String name = '다트';
  const String name2 = '플러터';

  name = 'dart'; // 에러 발생.
  name2 = 'flutter'; // 에러 발생.
}
final, const로 (상수) 선언 시 같은 타입이더라도 재 할당이 불가능하다.

 

void main() {
  final name = '다트';
  const name2 = '플러터';
}
추가적으로 변수 선언 시의 타입을 생략할 수 있다.

 

void main() {
  DateTime now = DateTime.now();

  print(now); // 2022-08-21 12:32:05.989
}
해당 코드(DateTime now = DateTime.now();)는 코드가 실행될 때(런타임)의 시간이 출력 된다.

 

void main() {
  final DateTime now = DateTime.now();
  const DateTime now2 = DateTime.now(); // 에러 발생.
}
final - 런타임 시점에 상수가 된다. (런타임 시간을 출력해주는 메소드기 때문에 final로 사용 가능하다.)
const - 컴파일 시점에 상수가 된다. (컴파일 이후로는 값을 변경할 수 없다.)
정리 - DateTime.now() 메소드는 런타임 시점의 시간을 출력해 준다.
          그러므로 런타임 시점에 상수가 되는 final로 사용이 가능하지만,
          컴파일 시점에 상수가 되는 const로는 사용할 수 없는것이다.
          참고로 실행 순서는 컴파일 -> 런타임이다.
추가 정보 - https://medium.com/dartlang-korea/dart-final-%EA%B3%BC-const-bc8c6c024ef4

 

11. 연산자 Operator

void main() {
  int number = 2;

  // 기본적인 연산들
  print(number + 1);
  print(number - 1);
  print(number * 2);
  print(number / 2);
  print(number % 2);

  // ++ 위치에 따라 출력값이 달라진다. (--도 동일하다.)
  print(++number); // 3 (2에서 +1 된 후 출력됨.)
  print(number++); // 2 (바로 위의 코드가 없다고 가정 : 2를 출력 한 후, +1이 됨.)
}
비교 연산자와(>, <, >=, <=, ==, !=) +=, -= 등 자바스크립트와 거의 유사하게 동작하므로 추가 내용은 생략한다.

 

void main() {
  int? number = 5; // nullable
  number = null; // number 변수에 null 재 할당
  
  number ??= 7;
  print(number); // 7
}
 변수명 ??= 재 할당값  : 만약 변수가 null이면 해당 값을 재 할당한다.

 

void main() {
  int number = 1;

  print(number is int); // true
  print(number is String); // false
  
  print(number is! int); // false
  print(number is! String); // true
}

 

12. List

void main() {
  List<String> animals = ['사자', '호랑이', '코끼리']; // String 타입의 요소값만 넣을 수 있다.

  print(animals[0]); // 사자

  List<int> integers = [1, 2, 3]; // ⭕
  List<int> integers2 = [1, 2, 3.0]; // ❌ double 타입의 값을 넣을 수 없다.

  List<double> doubles = [1.2, 3.0, 7] // ⭕ int 타입의 값이 들어가진다.
}
double 형의 List인 경우 정수값을 넣어도 에러가 발생하지 않는다. 자동적으로 7.0으로 인식하는거 같다. (주관적 해석)

 

void main() {
  List<String> colors = ['빨강', '노랑'];

  colors.add('초록'); // List의 맨 뒤에 값 추가하기.  
  print(colors); // [빨강, 노랑, 초록]

  colors.remove('노랑'); // List에서 '노랑' 값 제거하기.
  print(colors); // [빨강, 초록]

  print(colors.indexOf('초록')); // 1 (해당 값의 index 번호 출력하기.)
}
자바스크립트의 Array와 유사하다.

 

13. Map

void main() {
  // Key & Value
  Map<String, String> korEng = {
    '종이': 'paper',
    '테이프': 'tape',
  };
  print(korEng); // {종이: paper, 테이프: tape}

  korEng.addAll({
    '물': 'water',
  }); // Map 요소 추가하기.
  print(korEng); // {종이: paper, 테이프: tape, 물: water}

  // 요소를 추가하는 또 다른 방법
  // 대괄호[]엔 Key 값, 할당할 값엔 Value 값을 넣어준다. addAll()과 동일하다.
  // 같은 방법으로 기존의 Key에 Value 값을 재 할당할 수도 있다.
  korEng['컴퓨터'] = 'computer';
  print(korEng['종이']; // paper (무조건 Key 값으로 찾아야 한다. 그리고 해당 Key 값이 없는 경우 null이 출력된다.)
}

 

void main() {
  print(korEng); // {종이: paper, 테이프: tape, 물: water}
 
  korEng.remove('테이프'); // Key 값을 이용해 요소를 삭제하기.
  print(korEng); // {종이: paper, 물: water}

  print(korEng.keys); // (종이, 물) (Key 값만 출력하기.)
  print(korEng.values);  // (paper, water) (Value 값만 출력하기.)
}

 

14. Set

void Main() {
  final Set<String> colors = {
    'red',
    'yellow',
    'green',
  };

  colors.add('red'); // red 요소 추가하기.
  print(colors); // {red, yellow, green} (중복값이라 추가되지 않았다.)

  print(colors.contains('blue'); // false (Set 변수 안에 찾는 값이 포함되어 있는지 boolean 타입으로 반환된다.)
}
⭐ Set은 중복값을 포함하지 않는다.

 

15. 반복문 Loop

void main() {
  print(colors); // {red, yellow, green}

  for (String color in colors){
    print(color);
  };

  // red
  // yellow
  // green
  // 요소값이 차례대로 출력된다.
}
대부분의 반복문들이 자바스크립트와 유사하다.

 

16. 열거 Enum

// Enum은 main의 바깥에서 선언해야 한다.
enum Status {
  request, // 요청
  pending, // 대기
  approval, // 승인
}

void main() {
  Status status = Status.pending; // 대기

  if(status == Status.pending){
    print('대기중입니다.');
  } else if (status == Status.request){
    print('요청중입니다.');
  } else {
    print('승인되었습니다.');
  }

  // 대기중입니다.
}
enum은 일종의 타입과 같다.
해당 Status에는 3가지의 값(request, pending, approval)만 존재한다고 알려줄 수 있다. 
이외의 값을 할당하면 에러가 발행하여, 사전에 오류를 방지할 수 있다.

 

18. 함수 Function

addNumbers(int a, int b) {
  print(a + b);
}

void main() {
  addNumbers(5, 3); // 8
}
자바스크립트와는 다르게 function 선언을 생략한다.

 

addNumbers(int a, int b, [int c = 0]) {
  print(a + b + c);
}

void main() {
  addNumbers(1, 2); // 3
  addNumbers(1, 2, 3); // 6
}
optional parameter : 있어도 되고 없어도 되는 파라미터로 대괄호[]로 감싸준다.
default parameter : 인자 값을 넘기지 않았을 때의 기본값을 설정해 줄 수도 있다.

 

addNumbers({
  required int a,
  required int b,
}) {
  print(a + b);
}

void main() {
  addNumbers(a: 1, b: 2); // 3
  addNumbers(b: 1, a: 2); // 3
}
named parameter : 이름이 있는 파라미터. 인자 값을 넘겨줄 때 파라미터의 이름을 써주어야 한다.
이름과 함께 인자 값을 넘기기 때문에 순서가 변경되어도 상관없다.

 

addNumbers({
  required int a,
  int b = 0,
}) {
  print(a + b);
}

void main() {
  addNumbers(a: 1); // 1
  addNumbers(a: 1, b: 2); // 3
}
required를 빼고 기본값을 주면 named parameteroptional parameter처럼 사용할 수 있다.

 

int addNumber(int a, int b){
  return a + b;
}
기본적으로 return 값이 없는 함수는 함수명 앞에 void가 생략되어 있다고 생각하면 된다.
함수명 앞에는 함수의 리턴 타입을 지정해 주면 된다.
예시의 addNumber 함수는 정수 a, b를 인자 값으로 받아서 둘의 합계를 리턴하기 때문에 정수를 리턴해 주게 된다.
그러므로 void 대신에 int를 적어주어야 한다.

 

int addNumbers(int a, {
  required int b,
}) {
  return a + b;
}

void main() {
  addNumbers(3, b: 5); // 8
  addNumbers(b: 5, 3); // 8 (순서는 상관 없다.)
}
기본 파라미터(positional parameter)와 named parameter를 함께 사용할 수 있다.

 

19. 화살표 함수 Arrow function

int addNumbers(int a, int b) => a + b;
함수를 간결하게 표현할 수 있다.

 

20. Typedef

typedef Operation = int Function(int a, int b);

int add(int a, int b) => a + b;
int subtract(int a, int b) => a - b;

// 위의 함수를 실용성있게 발전 시켜보면
int calc(int a, int b, Operation operation) => operation(a, b);

void main() {
  Operation operation = add;
  print(operation(10, 5)); // 15

  Operation operation2 = subtract;
  print(operation2(10, 5)); // 5

  print(calc(3, 3, add)); // 6
}
파라미터에 operation을 추가하여 사용하면 훨씬 효율적이다.

 

21. 형변환 Method

void main() {
  List<String> singer = ['아이유', '에스파', '블랙핑크'];
  
  print(singer);
  print(singer.asMap()); // List => Map 변환 메소드
  print(singer.toSet()); // List => Set 변환 메소드
  
  // [아이유, 에스파, 블랙핑크]
  // {0: 아이유, 1: 에스파, 2: 블랙핑크}
  // {아이유, 에스파, 블랙핑크} Set은 중복 제거됨.
  
  // ------------------------------------------------------
  
  print(singer.asMap().keys); // .toList() 추가하면
  print(singer.asMap().values); // .toList() 추가하면
  
  // (0, 1, 2) => [0, 1, 2]
  // (아이유, 에스파, 블랙핑크) => [아이유, 에스파, 블랙핑크]
  
  // ------------------------------------------------------
  
  Set singerSet = Set.from(singer); // List => Set 변환 메소드
}

 

 

 

 

'DART' 카테고리의 다른 글