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이 그렇게 헷갈렷던 기억도 함께……ㅠㅠㅎㅎ
잘 보고 갑니당!