개요
오늘은 Flutter의 프로그래밍 언어 Dart의 문법에 대해서 알아보겠습니다.
프로그래밍 언어의 문법은 경험상 부연 설명 보다는 샘플 코드를 살펴보는 것이 더 효율적으므로
몇 개의 챕터로 나누어 기본 문법에 소개하겠습니다.
오늘의 포스팅에서 소개할 문법은 아래와 같습니다.
- 출력문
- 변수의 선언
- dynamic
- final과 const
- dart의 자료형
- dart의 컬렉션(Collections)
- Enum
1. 출력문
DART의 출력문은 아래와 같습니다.
void main(){
print('hello world!');
}
2. 변수의 선언
dart에서 변수의 선언은 var을 사용합니다. var는 타입 캐스팅을 지원하므로,
리터럴 값(1, false, "Hello World" 등)과 같은 실제 데이터가 입력되었을 때 그 자료형이 확정됩니다.
즉, 다른 프로그래밍 언어 등에서도 제공하는 '지연 초기화'가 가능합니다.
// fluter의 변수 선언
void main(){
// 변수의 선언
var name = 'hello world!';
print(name); // hello world!
// 변수의 재할당
name = 'hello monkey!';
print(name); // hello monkey!
var hello;
hello = 123;
print(hello); // 123
}
3. dynamic
dart에서는 Java의 Objec, Kotlin의 Any 처럼 어떤 자료형이든 담을 수 있는 변수를 선언할 수 있습니다.
이는 자바스크립트의 변수(var, let 등)와도 유사한 문법으로 보입니다.
void main(){
// dynamic을 통해 서로 다른 자료형 변수 담을 수 있음
dynamic name = 'hello wolrd!';
print(name); // hello wolrd!
name = 1;
print(name); // 1
}
4. final과 const
dart에서는 값이 변하지 않는 변수, 즉 상수 자료 형을 두 가지 지원합니다. ( final과 const )
이 두 자료형은 빌드 시점이나 런타임 중 검증하는 시점이 중요한 경우 용례가 달라질 수 있습니다.
즉, 빌드 시점에 상수를 확정해야 하는 경우 const를 사용해야하고, 런타임 시에 확정해야 하는 경우 final을 사용해야 합니다.
String과 같은 자료형은 어느 시점에서 검증하더라도 가능하므로 아래와 같이 작성할 수 있습니다.
반면에 DateTime과 같이 '시점'이 정해진 데이터의 경우에는 아래와 같이 구분하여 사용해야 합니다.
void main(){
final String name = 'black monkey';
// name = 'yellow monkey' // Error: Can't assign to the final variable 'name'.
print(name); // black monkey
const String name2 = 'pink banana';
// name2 = 'yello banana'; // Error: Can't assign to the const variable 'name2'.
print(name2); // pink banana
// final -> 런타임 상수
// const -> 빌드 타임 상수
final DateTime now = DateTime.now();
print(now); // ok
// const DateTime now2 = DateTime.now(); // Error: Cannot invoke a non-'const' constructor where a const expression is expected. Try using a constructor or factory that is 'const'.
// print(now2)
}
5. dart의 자료형
dart에서는 Dart는 모든 것이 객체이며, Dart에서는 원시형(primitive type)과 참조형(reference type) 데이터가 모두 객체로 취급됩니다. 그러나 개념적으로는 원시형과 참조형 데이터를 구분할 수 있습니다.
dart에서 개념적으로 구분되는 원시형(primitive type) 타입의 자료형은 아래와 같습니다.
void main(){
String pet = '고양이';
int age = 123;
double avgAge = 12.3;
bool isAdult = false;
print(pet);
print(age);
print(avgAge);
print(isAdult);
isAdult = true; // re-allocate ok!
print(isAdult);
// var is for type late init!
var myType = 123;
print(myType);
myType = 345; // ok
print(myType);
// myType = false; // Error: A value of type 'bool' can't be assigned to a variable of type 'int'.
}
또한, dynamic을 사용하지 아니한 모든 자료형의 경우 한번 자료형이 확정된 경우에는 다른 타입의 데이터를 넣을 수 없습니다.
💡 여기서 잠깐, dart에는 long과 float 자료형이 없나요?
dart에서 정수형에 해당하는 자료형은 int를 사용합니다. 그리고, 이 범위는 플랫폼이 몇 비트를 채택했는지에 따라 그 크기가 달라질 수 있습니다. 가령 32비트 체제에서는 대략 -2^31부터 2^31-1까지의 범위를 가집니다. 그러나, 64비트 체제에서는 대략 -2^63부터 2^63-1까지의 범위를 가집니다.
그럼에도 불구하고 이러한 범위를 넘어서는 정수형 자료형은 BigInt 라이브러리를 사용하여 처리할 수 있습니다.
또한, float과 같은 부동 소수점을 나타낼 수 있는 자료형의 경우도 지원하지 않습니다.
그러나, 이보다 큰 범위를 갖는 double을 사용할 수 있기 때문에, 64비트의 부동 소수점 수를 나타낼 수 있습니다.
6. dart의 컬렉션(Collections)
dart에서는 하나의 변수에 여러 개의 데이터를 담을 수 있는 자료형을 컬렉션이라고 정의합니다.
dart의 컬렉션은 상호간의 형변환이 자유로워 목적에 따라 다양한 자료형을 쉽게 변환 및 사용할 수 있습니다.
6.1. 리스트(List)
void main(){
// collections -> List
List<String> petList = ['Cat', 'Dog', 'Bird'];
print(petList); // [Cat, Dog, Bird]
// referece with index!
print(petList[0]); // Cat
print(petList[2]); // Bird
print(petList.length); // list's length : 3
petList[2] = 'Bee';
print(petList[2]); // Bee
// List's for-each
petList.forEach((pet){
print(pet);
});
// add
petList.add("Lion"); // 쌍 따옴표도 가능
print(petList); // [Cat, Dog, Bee, Lion]
print(petList.length); // 4
// add All
var otherPetList = ["Tiger", "Bear", "Elephant"];
petList.addAll(otherPetList);
print(petList); // [Cat, Dog, Bee, Lion, Tiger, Bear, Elephant]
}
6.2. 컬렉션의 스트림(Stream) 메서드 where, map, reduce, fold
void main(){
// collections -> List
List<String> petList = ['Cat', 'Dog', 'Bird'];
// where , 조건을 만족하는 데이터의 필터링
final longAnimal = petList.where( // type is Iterable!
(name) => name.length > 3 // 4글자 이상인 동물만!
);
print(longAnimal); // (Lion, Tiger, Bear, Elephant)
// type cast to List?
var longAniamlList = longAnimal.toList(); // Iterable → List
print(longAniamlList); // [Lion, Tiger, Bear, Elephant]
// map, 모든 값에 대해 동일한 '처리'를 해줄 때
final headAinmals = petList.map((name)=> 'Pet $name');
print(headAinmals); // (Pet Cat, Pet Dog, Pet Bee, Pet Lion, Pet Tiger, Pet Bear, Pet Elephant) type is Iterable
// reduce, 람다 함수(익명 함수)의 전달, 컬렉션이 있는 특정 값을 하나로 합치는 연산 등
// 단, reduce로 리턴하는 값은 컬렉션의 요소의 값과 타입이 일치해야함
// 배열의 값이 int라면 int, String이라면 String 등으로 고정!
final String allName = petList.reduce((value, element) => value + ', '+ element); // `value + ', ' + element'라는 형태의 익명 함수를 받는 형식, 결과적으로 전체 값을 더하는 연산을 수행하게 됨.
// final int allLength = petList.reduce((value, element) => value + 0 + element); // Error: A value of type 'String' can't be assigned to a variable of type 'int'.\
print(allName); // Cat, Dog, Bee, Lion, Tiger, Bear, Elephan
// fold, reuce의 상위 호환 버전 느낌, 리턴 타입이 반드시 배열을 구성하는 요소와 자료형과 같지 않아도 됨!
final int allLength = petList.fold<int>(0, (value, element) => value + element.length);
print(allLength); // 30
}
6.3. Map
void main(){
// collections -> Map
Map<String, String> books = {
'Clean Code': 'Robert C. Martin', // key : value 형식으로 입력!
'The Pragmatic Programmer': 'Andrew Hunt, David Thomas',
'Effective Dart': 'Google',
'Design Patterns': 'Erich Gamma, Richard Helm, Ralph Johnson, John Vlissides',
'Refactoring': 'Martin Fowler'
};
// 맵 출력
print('First Book Author is ${books["Clean Code"]}'); // First Book Author is Robert C. Martin
// Map's for-each
books.forEach((title, author) {
print('$title by $author');
});
// key 값 반환하기
print(books.keys); // key 값 , type은 Interbale 이므로 toList() 메서드를 통해 타입 변환 가능!
print(books.values); // value 값, type is Iterable
}
6.4. Set
void main(){
// collections -> Set
var petPool1 = { "Lion", "Tiger", "Bear", "Elephant", "Zebra" };
Set<String> petPool2 = { "Giraffe", "Rhinoceros", "Hippopotamus", "Cheetah", "Gorilla" };
print(petPool1); // {Lion, Tiger, Bear, Elephant, Zebra}
print(petPool2); // {Giraffe, Rhinoceros, Hippopotamus, Cheetah, Gorilla}
// contains, 값이 있는지 확인
print(petPool1.contains("Giraffe")); // false
print(petPool1.contains("Lion")); // true
print(petPool2.contains("Giraffe")); // true
print(petPool2.contains("Lion")); // false
var petPoolList1 = petPool1.toList(); // set -> List 변환 가능!
print(petPoolList1); // [Lion, Tiger, Bear, Elephant, Zebra]
// from(), List -> Set 변환
var parsedSet = Set.from(petPoolList1);
print(parsedSet); // {Lion, Tiger, Bear, Elephant, Zebra}
}
7. Enum
Enum, 즉 열거형은 상수(변경할 수 없는 변수) 그룹을 나타내는 특별한 "클래스"입니다.
어떤 분류에 속하는 데이터에서 유형을 정하는 경우, 예컨데 음료의 종류 또는 직업의 종류 등을 표현하는 등의 사례에서 활용될 수 있습니다.
dart에서 Enum은 아래와 같이 사용할 수 있습니다.
enum Drink {
coffee,
tea,
juice,
soda,
}
void main(){
var drinkCoffee = Drink.coffee;
print(drinkCoffee); // Drink.coffee
}
'프로그래밍 언어 기초 > Dart' 카테고리의 다른 글
[Dart] Dart 기본 문법4 [비동기, async, await, Future, Stream] (0) | 2024.03.30 |
---|---|
[Dart] Dart 기본 문법3 [클래스, 생성자, 오버라이딩, static, 추상, 제네릭] (0) | 2024.03.29 |
[Dart] Dart 기본 문법2 [제어문, 반복문, 함수, 익명 함수, 람다 함수, 예외 처리(try-catch)] (1) | 2024.03.28 |