void main() {
num a = 1.234; // 숫자
int b = 1; // 정수
double c = 11.11; // 부동 소수점 숫자
String name = '지은'; // 문자열
bool isAdult = true; // 참 또는 거짓
List<int> numberList = [1, 2, 3]; // 배열
Map<String, int> person = {'age': 20, 'money': 10000}; // Map
Set<String> colorSet = {'red', 'orange', 'yellow'}; // Set
}
void main() {
List<Map<String, Object>> players = [
{'name': '지은', 'xp': 999},
{'name': '지지', 'xp': 1}
];
}
collection if: Dart의 리스트에 요소를 조건부로 추가할 수 있게 해주는 간편한 방법
void main() {
bool giveMeFive = true;
var numbers = [1,
2,
3,
4,
if(giveMeFive) 5
];
print(numbers); // [1, 2, 3, 4, 5]
}
collection for리스트를 생성할 때 루프나 반복문을 사용해 간단하게 요소를 추가하는 방법
void main() {
var oldFriends = ['지은', '지지'];
var newFriends = [
'벨라',
'홍시',
for(var friend in oldFriends) '🤍 $friend'
];
print(newFriends); // [벨라, 홍시, 🤍 지은, 🤍 지지]
}
$와${}Dart 문자열 내에서 변수와 표현식을 삽입려면
$와${}을 사용한다.
$는 단순한 변수를 문자열에 삽입하는 데 사용되며,${}는 변수와 표현식을 복잡한 문자열 중에 포함시키는 데 사용된다.void main() { var name = '지은'; var age = 10; var greeting = 'Hello, my name is $name and I am ${age + 2}!'; print(greeting); // Hello, my name is 지은! and I am 27! }
collection if 와 collection for를 둘 다 사용한 예시void main() {
bool giveMeFive = true;
var numbers = [
for (int i = 1; i <= 4; i++) i,
if (giveMeFive) 5,
];
print(numbers); // [1, 2, 3, 4, 5]
}
: 키(key)와 값(value) 쌍으로 데이터를 저장하는 데이터 구조
void main() {
Map<String, dynamic> players = {
'name': '지은',
'xp': 20,
'isAdult': true,
};
// 맵의 키는 String 타입, 값은 dynamic 타입
Map<int, List<bool>> mapExample = {
1: [true, false],
2: [false, false],
3: [true, true],
};
// 맵의 키는 int 타입, 값은 Bool을 요소로 갖는 List 타입
}
var playerName = player['name']; // '지은'
var playerXP = player['xp']; // 20
player['isAdult'] = fase;
: 고유한 값을 저장하는 데이터 구조로, 중복된 값을 허용하지 않는다.
void main() {
Set<int> numberSet = {1, 2, 3, 4};
numberSet.add(1);
numberSet.add(1);
numberSet.add(1);
print(numberSet); // {1, 2, 3, 4} 중복된 값은 무시된다.
}
numberSet.add(1);
numberSet.remove(1);
Dart 함수는 반환 타입, 함수 이름, 매개 변수, 함수 본문으로 구성된다.
함수의 이름 앞에는 함수가 리턴하는 값의 타입을 적어줘야 한다. 아래 예시에서 void는 아무것도 리턴하지 않는다는 뜻이다.
또한 매개변수에도 타입을 지정해줘야 한다. 아래 예시는 문자열(String) 타입의 name 매개변수를 받고 있다.
void sayHello(String name) { // 아무 것도 리턴하지 않는 함수
print('Hello $name!');
}
void main() {
sayHello('지은'); // 함수 호출 | 'Hello 지은!'
}
아래처럼 만약에 문자열을 리턴한다면, String을 리턴하는 함수라고 명시해줘야 한다.
String sayHello(String name) { // 문자열을 리턴하는 함수
return 'Hello $name!';
}
void main() {
print(sayHello('지은')); // 'Hello 지은!'
}
Dart는 화살표 함수 표기법을 제공하여 함수를 간결하게 작성할 수 있다.
return 구문과 중괄호({})를 생략하고 화살표(=>)를 사용하면 된다.
String sayHello(String name) => 'Hello $name!';
void main() {
print(sayHello('지은')); // 'Hello 지은!'
}
함수 호출 시, 명명된 인자를 사용하여 인자의 순서를 신경 쓰지 않고 전달할 수 있다.
또한 명명된 인자를 사용하면 가독성이 높아지며, 자동 완성 기능도 사용할 수 있다.
명명된 인자를 사용하려면 함수의 파라미터를 중괄호 {}로 감싸면 된다.
String sayHello({
required String name,
required int age,
required String country
}) {
return 'Hello $name! You are $age, and come from $country.';
}
void main() {
print(sayHello(
country: 'Korea',
name: '지은',
age: 27,
)); // Hello 지은! You are 27, and come from Korea.
}
null safety로 인해 에러가 뜨므로 required modifier를 붙여준다.
required는 해당 인자가 필수임을 나타낸다.
또는 기본값(default value)을 지정할 수 있다.
이는 함수 호출 시 해당 인자가 전달되지 않을 경우, 기본값을 사용하게 한다.
String sayHello({
String name = 'defaultName',
int age = 0,
String country = 'defaultCountry'
}) {
return 'Hello $name! You are $age, and come from $country.';
}
void main() {
print(sayHello()); // Hello defaultName! You are 0, and come from defaultCountry.
}
선택적 위치 매개변수는 함수의 파라미터 중 일부 파라미터가 선택적으로 값을 가질 수 있음을 나타내는 방법이다. 선택적 위치 매개변수는 함수를 호출할 때 인수를 전달하지 않아도 기본값을 가지고 있다.
선택적 위치 매개변수를 사용하려면 매개변수를 대괄호 []로 감싸고 필요한 경우 기본값을 주면 된다.
void main() {
String sayHello(
String name,
int age,
[String country = 'defaultCountry']
) => 'Hello $name! You are $age, and come from $country.';
print(sayHello('지은', 27)); // Hello 지은! You are 27, and come from defaultCountry.
print(sayHello('지은', 27, 'Korea')); // Hello 지은! You are 27, and come from Korea.
}
String capitalizeName(String? name) {
if (name != null) { // name이 null이 아니라면
return name.toUpperCase(); // name.toUpperCase()를 리턴한다.
}
return 'NAME'; // if 조건문에 들어가지 않은 경우, 'NAME'을 리턴한다.
}
void main() {
print(capitalizeName('jieun')); // JIEUN
print(capitalizeName(null)); // NAME
}
위의 코드를 삼항 연산자를 사용하면 간단하게 아래처럼 표현할 수 있다.
삼항 연산자는 조건문을 간결하게 표현하는 방법으로 조건 ? 조건이 참인 경우 실행할 표현식 : 조건이 거짓인 경우 실행할 표현식으로 구성된다.
String capitalizeName(String? name) => name != null ? name.toUpperCase() : 'NAME';
// name이 null이 아닌 경우 name.toUpperCase()를 반환하고, 그렇지 않으면 'NAME'을 반환한다.
void main() {
print(capitalizeName('jieun')); // JIEUN
print(capitalizeName(null)); // NAME
}
Null-aware 연산자는 ?.로 표시되며, 객체가 null이 아닌 경우에만 해당 객체에서 메서드를 호출하거나 속성에 접근할 수 있게 한다.
객체가 null이면 예외를 발생시키지 않고 null을 반환한다.
String capitalizeName(String? name) => name?.toUpperCase() ?? 'NAME';
void main() {
print(capitalizeName('jieun')); // JIEUN
print(capitalizeName(null)); // NAME
}
좌항이 null인 경우에 우항의 값을 반환하는 연산자
주로 기본값을 설정하거나, 값이 null인 경우 대체값을 제공하는 데 사용한다.
String name = null;
String result = name ?? 'defaultName';
print(result); // 'defaultName'
좌항이 null인 경우에 우항의 값을 좌항에 할당하는 연산자
좌항에 이미 값이 있거나 null이 아니면 할당하지 않는다.
변수에 기본값을 설정하거나, 변수가 아직 초기화되지 않았을 때 초기값을 제공하는 데 유용하다.
void main() {
String? name; // 초기값은 null
name ??= 'jieun'; // name이 null이므로 'jieun'이 할당된다.
print(name); // jieun
name ??= 'GG'; // name에 이미 값이 있으므로 할당되지 않는다.
print(name); // jieun
}
typedef는 데이터 유형에 별칭(alias)를 불여줄 수 있게 해준다.
이는 기존 데이터 유형을 다른 이름으로 참조할 수 있게 해주므로 코드를 더 읽기 쉽게 만들고, 복잡성을 줄이며, 코드를 재사용하고 유지 관리하기 쉽게 만들어준다.
TypeScript의 Interface랑 비슷한 개념같지만, Dart에서는 이 별칭을 함수 유형과 데이터 유형에 모두 사용할 수 있다.
typedef ListOfInts = List<int>; // List<int> 의 별칭을 ListOfInts로 정의
ListOfInts reverseListOfNumbers(ListOfInts list) { // List<int> 대신 사용
var reversed = list.reversed;
return reversed.toList();
}
void main() {
print(reverseListOfNumbers([1,2,3])); // [3,2,1]
}
오랜만에 보니까 기억이 새록새록이네요 ㅎㅎ
Map set이 그렇게 헷갈렷던 기억도 함께……ㅠㅠㅎㅎ
잘 보고 갑니당!