1. 컬렉션 (Collections)
var numbers = [1, 2, 3, 4, 5];
컬렉션은 여러 개의 값을 그룹으로 묶어서 효율적으로 관리할 수 있는 자료 구조이다. 컬렉션을 사용하면 데이터를 더 쉽게 처리하고 관리할 수 있다. 주요 컬렉션에는 List, Set, Map이 있다.
1-1. List
List는 순서가 있는 값들이 묶인 형태이다. 배열이라고도 불리며, 리스트 안의 요소는 순서를 가지며 접근할 수 있다.
생성 방법
List<타입> [변수 이름] = [요소];
List<int> numbers = [1, 2, 3, 4, 5];
각 요소는 ,로 구분한다.
빈 List 만들기
List<int> numbers = [];
요소가 없는 빈 리스트도 만들 수 있다.
타입 추론
var numbers = [1, 2, 3, 4, 5];
이때 numbers는 List<int>로 타입이 추론된다.
변하지 않는 List
final numbers = [1, 2, 3, 4, 5];
const names = ['Alice', 'Bob', 'Henry'];
요소가 변하지 않는 경우 final이나 const로 선언할 수 있다.
특징
- 리스트의 요소는 모두 같은 타입이어야 한다.
- 다른 타입이 포함되면 오류가 발생한다.
예시:
List<String> fruits = ['사과', '파인애플', '오렌지', 8];
8은 int이기 때문에 오류가 발생한다.
Index 접근 첫 번째 요소는 인덱스 0부터 시작한다.
print(numbers[0]); // 1
음수 인덱스를 사용할 수 없다.
요소 수정
numbers[3] = 2;
print(numbers[3]); // 2
List의 길이
print(fruits.length); // 3
요소의 개수를 구할 수 있다.
isEmpty, isNotEmpty
print(numbers.isEmpty); // true
print(fruits.isNotEmpty); // true
리스트가 비었는지 여부를 판별할 수 있다.
요소 추가
fruits.add('복숭아');
fruits.addAll(['포도', '귤']);
remove()는 특정 요소를, removeAt()은 인덱스를 사용해 요소를 삭제한다.
1-2. Set
Set은 중복되지 않은 값들이 묶인 형태이다. 수학에서 말하는 집합과 같아서 중복된 값은 하나만 유지된다.
생성 방법
Set<타입> [변수 이름] = {요소};
Set<int> numbers = {1, 2, 3, 4, 5};
빈 Set 만들기
Set<int> numbers = {};
Set 특징
- Set의 요소는 모두 같은 타입이어야 한다.
- 중복된 값이 있으면 하나를 제외하고는 모두 무시된다.
예시:
var fruits = {'사과', '파인애플', '사과'};
결과: {'사과', '파인애플'}
요소 추가
fruits.add('복숭아');
fruits.addAll({'포도', '귤'});
요소 삭제
fruits.remove('파인애플');
contains()
print(fruits.contains('사과')); // true
print(fruits.contains('포도')); // false
특정 요소가 존재하는지 확인할 수 있다.
1-3. Map
Map은 키(Key)와 값(Value)이 묶인 하나의 쌍으로 이루어진 자료구조이다.
생성 방법
Map<key 타입, value 타입> 변수 이름 = {key: value};
Map<String, String> people = {'Alice': 'Teacher', 'Bob': 'Student'};
빈 Map 만들기
Map<String, String> people = {};
Map 특징
- 키와 값은 각각 타입이 같아야 한다.
- 키는 중복될 수 없고, 값은 중복될 수 있다.
예시:
Map<String, int> people = {'Alice': 25, 'Bob': 30, 'Alice': 23};
결과: {'Alice': 23, 'Bob': 30}
요소 추가
people['Charlie'] = 'Engineer';
요소 삭제
people.remove('Alice');
containsKey(), containsValue()
print(people.containsKey('Bob')); // true
print(people.containsValue(30)); // true
키나 값이 존재하는지 확인할 수 있다.
이렇게 각 컬렉션은 특정 상황에 따라 적합하게 사용될 수 있다. List는 순서가 중요한 데이터에, Set은 중복을 제거하고 싶은 데이터에, Map은 키와 값의 쌍으로 데이터를 관리할 때 유용하다.
- List vs Set
- List는 순서가 있고, 인덱스를 사용하며, 중복을 허용하는 데이터 구조입니다.
- Set은 순서가 없고, 인덱스 개념이 없으며, 중복된 값을 허용하지 않습니다.
List | Set | |
순서 유무 | O | X |
Index 유무 | O | X |
중복 허용 | O | X |
2. 열거형 (Enumerations)
열거형은 여러 개의 상수 값들을 묶어서 하나의 타입으로 정의할 수 있게 해주는 기능이다. 각 값은 고유한 이름을 가지며, 값들을 일관되게 관리할 수 있도록 돕는다.
어떤 친구인가요?
열거형은 상수들을 하나의 묶음으로 정의하는 방법이다. 이 상수들은 값이 변하지 않으며, 이름을 통해서 각각의 상수값에 접근할 수 있다. 예를 들어, 색상, 동물, 요일 등과 같이 한정된 선택지들이 있을 때 유용하게 사용한다.
어떻게 생겼나요?
열거형은 enum 키워드를 사용해서 정의한다. 각 항목들은 {} 중괄호 안에 나열되며, 쉼표로 구분한다. 또한, 열거형의 이름을 지정해줘야 한다.
예시 1: 색상을 나타내는 열거형
enum Color { red, green, blue }
예시 2: 동물 종류를 나타내는 열거형
enum Animal {
cat,
dog,
tiger,
elephant,
}
특징
2-1. 값에 접근하기: 열거형 값에 접근할 때는 enum 이름을 통해 값을 호출할 수 있다.
var myFavoriteColor = Color.blue;
print(myFavoriteColor); // Color.blue
2-2. switch문 사용하기: switch문을 사용하면 열거형의 값에 따라 다양한 동작을 할 수 있다. 예를 들어, 색상에 따라 다르게 처리하는 예 시이다.
var myFavoriteColor = Color.green;
var result = '내가 제일 좋아하는 색은 ';
switch (myFavoriteColor) {
case Color.red:
result += '빨간색';
break;
case Color.green:
result += '초록색';
break;
case Color.blue:
result += '파란색';
break;
}
print(result); // 내가 제일 좋아하는 색은 초록색
- switch문은 여러 가지 경우를 고려할 때 유용하다.
- break를 추가해줘야 각 case문을 벗어날 수 있다.
2-3. if문으로도 사용 가능: if문을 사용해서도 열거형을 처리할 수 있다. 다만, switch문이 더 적합한 경우가 많다
var myFavoriteColor = Color.green;
var result = '내가 제일 좋아하는 색은 ';
if (myFavoriteColor == Color.red) {
result += '빨간색';
} else if (myFavoriteColor == Color.green) {
result += '초록색';
} else if (myFavoriteColor == Color.blue) {
result += '파란색';
}
print(result); // 내가 제일 좋아하는 색은 초록색
2-4. 인덱스 값 확인하기: 열거형에 포함된 값들은 각각 고유한 인덱스를 가진다. 첫 번째 값은 0부터 시작한다. 이를 index 프로퍼티를 통해 확인할 수 있다.
print(Color.red.index); // 0
print(Color.green.index); // 1
print(Color.blue.index); // 2
2-5. 모든 열거형 값 가져오기: values를 사용하면 해당 열거형에 포함된 모든 값을 리스트 형태로 가져올 수 있다.
var colors = Color.values;
print(colors); // [Color.red, Color.green, Color.blue]
print(colors[1]); // Color.green
2-6. 이름 가져오기: name을 사용하면 각 열거형 값의 이름을 문자열로 가져올 수 있다.
print(Color.red.name); // red
언제 사용하나요?
- 열거형은 고정된 집합의 값들을 관리할 때 유용하게 사용된다. 예를 들어, 색상, 요일, 상태 코드, 동물 종류 등 고정된 값들로 작업할 때 주로 사용한다.
열거형 vs Set
- Set과 비슷하게 여러 값을 묶을 수 있지만, 열거형은 값이 변경 불가능하고, 순서가 있으며, 인덱스가 부여된다. 반면 Set은 순서가 없고 인덱스를 사용하지 않으며, 중복 값이 허용되지 않는다.
- 열거형의 특수한 점:
- enum 값은 값 추가나 삭제가 불가능하며, 처음 정의된 값들이 고정된다.
- enum은 중복을 허용하지 않는다. 예를 들어, 동일한 값을 두 번 정의하면 오류가 발생한다.
3. 함수 (Function)
함수란?
함수는 특정 작업을 수행하는 코드 블록이다. 입력을 받아서 특정 작업을 하고, 그 결과를 반환하는 코드 덩어리이다.
함수의 구성 요소
- 반환 타입
함수가 반환하는 값의 데이터 타입이다. 값을 반환하지 않으면 void로 설정한다. - 함수 이름
함수의 이름이다. 호출할 때 사용된다. - 매개변수
함수 내부로 전달되는 값이다. 1개 이상일 수 있으며, 개수에 제한이 없다. - 실행할 코드
함수가 호출되면 실행되는 코드 블록이다. - 반환값
함수가 실행된 후 반환되는 결과값이다.
함수의 형태
[반환 타입] [함수 이름]([매개변수 타입] [매개변수 이름]) {
return [반환값];
}
예시 1: printName 함수
void printName() {
print('강미래');
}
- 함수 이름: printName
예시 2: isOddNumber 함수
bool isOddNumber(int number) {
return number % 2 != 0;
}
- 반환 타입: bool
- 함수 이름: isOddNumber
- 매개변수 타입: int
- 매개변수 이름: number
- 반환값: number % 2 != 0
예시 3: add 함수
int add(int a, int b) {
return a + b;
}
- 반환 타입: int
- 함수 이름: add
- 매개변수 타입: int
- 매개변수 이름: a, b
- 반환값: a + b
함수 호출하기
함수 이름을 가지고 호출하면 된다.
void printName() {
print('강미래');
}
printName(); // 강미래
bool isOddNumber(int number) {
return number % 2 != 0;
}
bool isTwoOddNumber = isOddNumber(2);
print(isTwoOddNumber); // false
int add(int a, int b) {
return a + b;
}
int sum = add(2, 4);
print(sum); // 6
main() 함수
main() 함수란?
main() 함수는 모든 Dart 프로그램의 시작 지점이다. 이 함수가 없으면 프로그램을 실행할 수 없다.
특징
- main() 함수 안에 작성된 코드만 실행된다.
- 반환값이 없기 때문에 void로 설정된다.
void main() {
print('안녕하세요 !'); // 안녕하세요 !
}
매개변수 사용 예시
main() 함수는 List<String> 타입의 매개변수를 받을 수도 있다. 이 매개변수는 주로 터미널에서 인자를 받을 때 사용된다.
void main(List<String> arguments) {
print(arguments);
}
함수 사용 이유
함수는 특정 작업을 하나의 코드 덩어리로 만들어, 같은 작업을 여러 번 할 때 반복해서 코드를 쓰지 않도록 한다. 이를 통해 코드가 더 효율적이고 깔끔해진다.
함수를 사용하지 않은 예시
void main() {
int one = 1;
int two = 2;
print(one + two); // 3
int three = 3;
int four = 4;
print(three + four); // 7
int five = 5;
int six = 6;
print(five + six); // 11
int seven = 7;
int eight = 8;
print(seven + eight); // 15
}
함수를 사용한 예시
void printSum(int a, int b) {
print(a + b);
}
void main() {
printSum(1, 2); // 3
printSum(3, 4); // 7
printSum(5, 6); // 11
}
이렇게 함수를 사용하면 코드가 더 깔끔하고 효율적이다.
4. 제네릭 (Generics)
제네릭이란?
제네릭은 클래스나 함수에서 데이터 타입을 일반화하여 다양한 타입을 지원할 수 있게 해주는 기능이다. 제네릭에는 제네릭 클래스와 제네릭 함수가 있지만, 현재는 제네릭 함수에 대해서만 다룬다. 제네릭 클래스는 클래스에 대해 배운 후 설명할 것이다.
제네릭 함수의 형태
[타입 파라미터] [함수 이름]<타입 파라미터>([매개변수]) { … }
예시: getFirstElement 함수
T getFirstElement<T>(List<T> list) {
return list[0];
}
- 타입 파라미터는 보통 영어 대문자 하나로 표현된다. 예시로는 T, E, S 등이 있다.
- 실제로 코드에서 이 타입 파라미터 자리에 실제 데이터 타입을 넣으면 된다.
제네릭 함수 사용 예시
int getFirstNumber(List<int> numbers) {
return numbers[0];
}
String getFirstWord(List<String> words) {
return words[0];
}
void main() {
var numbers = [0, 1, 2, 3];
print(getFirstNumber(numbers)); // 0
var words = ['a', 'b', 'c'];
print(getFirstWord(words)); // a
}
위 코드처럼 각 타입에 맞는 함수가 각각 필요하다면 코드가 반복될 수 있다.
제네릭 함수로 만들기
T getFirstElement<T>(List<T> list) {
return list[0];
}
void main() {
var numbers = [0, 1, 2, 3];
print(getFirstElement(numbers)); // 0
var words = ['a', 'b', 'c'];
print(getFirstElement(words)); // a
}
- 제네릭 함수로 만들면, 다양한 타입에 대해 같은 코드를 재사용할 수 있다.
- 이로 인해 코드가 간결하고 효율적이며 재사용성이 높아진다.
제네릭을 사용하는 이유
제네릭을 사용하면 특정 타입에 의존하지 않고, 여러 타입에 대해 동일한 코드를 적용할 수 있다. 이렇게 하면 재사용성이 높은 코드를 작성할 수 있어 효율적인 개발이 가능하다.
'flutter앱개발과정' 카테고리의 다른 글
콘솔 쇼핑몰 - 트러블 슈팅(Troubleshooting) (0) | 2025.03.13 |
---|---|
dart문법 함수형 프로그래밍 (0) | 2025.03.12 |
dart 기본문법 공부 기록 (0) | 2025.03.10 |
dart문법 복습 - inflean강의 (0) | 2025.03.06 |
flutter 앱개발 - MacOS 환경세팅 (0) | 2025.03.05 |