다트) Dart 1 - 객체 선언 및 라이브러리 활용 정리
✨ 외부 패키지 사용하기
- pub.dev 사이트
- PLATFORM 호환 종류 확인
- Null safety 명시 확인 → 적용 개발 확인하기
- 외부 패키지 사용방법
- pubspec.ymal, 패키지와 버전을 명시 후 Pub get
- 터미널을 통해 ‘flutter pub add [패키지명]’ 입력
- 추가 결과 : pubspec.ymal에 추가되어있음
dependencies: flutter: sdk: flutter cupertino_icons: ^1.0.2 english_words: ^4.0.0 dev_dependencies: flutter_test: sdk: flutter
- 대부분의 패키지는 dependencies에 등록
- 앱 개발때만 이용하느 패키지는 dev_dependencies에 등록
- 패키지 이름과 버전을 명시(^는 지정되는 버전과 호환되는 모든 범위의 버전)
- 다트 엔진 라이브러리(의존성 설정 필요X)
플랫폼 종류 | 라이브러리 종류 | 지원하는 내용 |
---|---|---|
멀티 플랫폼 | dart:async | 비동기 프로그래밍 |
dart:collection | LinkedList, HashMap 등 집합 데이터 | |
dart:convert | JSON 같은 데이터의 인코딩과 디코딩 | |
dart:core | 내장(built-in) 타입, 컬렉션 등 | |
dart:developer | 디버거나 인스펙터 등 개발자 도구 | |
dart:math | 수학 함수 | |
네이티브 플랫폼 | dart:io | 파일, 소켓, HTTP 등 앱에서 발생하는 입출력 |
dart:isolate | 동시성 프로그래밍(일종의 스레드 프로그래밍) | |
웹 플랫폼 | dart:html | HTML 요소 |
dart:indexed_db | 키-값 형태의 데이터 저장 | |
dart:web_audio | 오디오 핸들링 | |
dart:web_gl | 3D 그래픽 | |
dart:web_sql | SQL 기반 데이터 저장 |
1. 다트 기본기능 알아보기
1) 선언, 라이브러리 불러오기
- 변수/함수/클래스 선언
int no = 10; void sayHello() { print('hello, $no'); } class User{ int no = 10; void sayHello() { print('world, $no'); } }
- 상대 경로로 불러오기
- 같은 프로젝트에 있는 다른 다트 파일 불러올 때
import '../outer_folder/outer_main.dart';
- 같은 프로젝트에 있는 다른 다트 파일 불러올 때
- package 접두사 불러오기
import 'package : [패키지 이름]'; import 'package :[다트 파일 이름].dart';
- dart 접두사로 불러오기
import 'dart:core'; import 'dart:async';
2) 외부에서 사용할 수 없게 제한하기
- public vs private (접근 제한자)
no1 = 20; // public _no2 = 30; // private
3) 식별자에 별칭 정의하기
- as 예약어
import 'test1.dart' as Test1; main() { no1 = 30; // 오류 Test1.no1 = 30; Test1.sayHello1(); Test1.User1 user1 = Test1.User1(); }
4) 특정 요소민 불러오기
- show
import 'test1.dart' show no1, User1; main() { no1 = 30; User1 user1 = User1(); // 클래스 선언 문법(클래스명 / 객체명 = 클래스명) sayHello1(); // 오류 }
- int, double처럼 class를 가져오기에 앞에 클래스명을 붙여주어야 한다.
5) 특정 요소 제거한 채 불러오기
- hide
import `test1.dart` hide sayHello1, User1; main() { no1 = 30; sayHello1(); // 오류 User1 user1 = User1(); // 오류 }
2. 라이브러리 만들기
1) 여러 파일을 하나로 묶어 import 하는 법
- 예시 : a.dart, b.dart파일을 myLib.dart파일로 묶어 사용하는 법
// a.dart part of my_lib; int aData = 10;
// b.dart part of my_lib; int bData = 20;
// myLib.dart library my_lib; part 'a.dart'; part 'b.dart';
- 불러오기
import 'myLib.dart'; main(){ print('$aData, $bData'); }
3. 데이터 타입과 널 안정성
1) 데이터 타입
- 타입 클래스
라이브러리 | 타입 클래스 | 데이터 |
---|---|---|
dart:core | bool | true, false |
double | 실수 | |
int | 정수 | |
num | 숫자(double과 int의 상위 클래스) | |
String | 문자열 | |
dart:typed_data | ByteData | 바이트 |
- 문자열 표현하기 : ‘ / “ / ‘’’ / “””
main() { String data1 = 'hello'; String data2 = 'world'; String data3 = ''' hello world '''; String data4 = """ hello world """; }
- 문자열 비교 : == / bool(true, false)
String str1 = 'hello'; String str2 = 'hello'; print(str1 == str2)
- 문자열 템플릿 : $
main() { int no = 10; String name = 'kkang' String myFun() { return 'kim'; } print('no : $no, name : $name, 10 + 20 : ${10 + 20}, myFun() : ${myFun()}') }
- 형 변환하기
main() { int n1 = 10; double d1 = 10.0; double d2 = n1; // 오류 int n2 = d1; // 오류 double d2 = n1.toDouble(); // 성공(int → double) int n2 = d1.toInt(); // 성공(double → int) }
main() { int n1 = 10; String s1 = '10'; String s2 = n1.toString(); // 성공(int → String) int n3 = int.parse(s1); // 성공(String → int) }
2) 상수 변수 - const, final
- 상수 변수란?
초기값을 대입한 후에 값을 바꿀 수 없는 변수
(1) Const : 컴파일 타임 상수 변수
- 초기값 대입 시점은 선언문 / 변숫값 변경할 시 오류
- 클래스 내부 선언 시 static
const String data1; // 오류 const String data2 = 'hello'; class User { static const String data3 = 'hello' void some() { const String data4 = 'hello'; data2 = 'world'; // 오류 data3 = 'world'; // 오류 data4 = 'world'; // 오류 } }
(2) final : 런 타임 상수 변수
- 초깃값을 대입 시점은 선언문 / 변숫값 변경할 시 오류
final int no1; // 초깃값이나 이후에 값을 대입하지 않아서 오류 class MyClass final int no2; MyClass(this.no2); void some() { final no3; no3 = 10; no3 = 20; // 값을 바꿀 수 없어서 오류 }
- MyClass(this.no2) def –init–이랑 비슷하다.
(3) 상수 변수와 문자열 템플릿
main() {
String s1 = 'hello';
const String s2 = 'world';
final String s3 = 'helloworld';
String s4 = '$s1, $s2';
const String s5 = '$s2';
const String s6 = '$s1, $s2, $s3'; // 오류
final String s7 = '$s1, $s2, $s3';
}
3) 선언 - var와 dynamic
(1) var : 타입 유추 / 타입 결정됨
var no = 10;
no = 20; // int로 결정
no = 'hello'; // 오류
(2) dynamic : 모든 타입의 데이터 대입 가능
dynamic data = 10;
data = 'hello';
data = true;
4) 컬렉션 - List, Set, Map
(1) List
- List 타입 미지정
main() { List List1 = [10, 'hello', true]; list1[0] = 20; list1[1] = 'world'; print('List : [${list1[0]}, ${list1[1]}, ${list1[2]}'); }
- List 타입 지정
main() { List<int> list2 = [10, 20, 30] list2[0] = 'hello'; // 오류 }
- List 요소 추가/제거
main() { List<int> list2 = [10, 20, 30]; print(list2); // [10, 20, 30] list2.add(40); // 추가 list2.add(50); // 추가 print(list2); // [10, 20, 30, 40, 50] list2.removeAt(0); // 제거, 인덱스 print(list2); // [20, 30, 40, 50]] }
- List 크기 지정
main() { var list3 = List<int>.filled(3, 0); print(list3); // [0,0,0] list3[0] = 10; list3[1] = 20; list3[2] = 30; print(list3); // [10,20,30] list3.add(40); // 오류 }
- 확장 가능하게 하기
main() { var list3 = List<int>.filled(3, 0, growable: true); print(list3); // [0,0,0] list3[0] = 10; list3[1] = 20; list3[2] = 30; print(list3); // [10,20,30] list3.add(40); print(list3); // [10,20,30, 0] }
- 확장 가능하게 하기
- 로직을 통해 List 선언 : <예시> index * 10
예시>
main() { var list4 = List<int>.generate(3, (index) => index * 10, growable: true); print(list4); // [0, 10, 20] }
(2) 집합 타입
-
list + <중복 미허용="">중복>
-
set 타입 지정
main() { Set<int> set1 = {10, 20, 30}; print(set1); // {10, 20} set1.add(30); set1.add(40); print(set1); // {10, 20, 30, 40} Set<int> set2 = Set(); set1.add(10); set1.add(20); print(set2); // {10, 20} }
(3) 맵 타입
- 키, 값 형태(Python dictionary)
main() { Map<String, String> map1 = {'one':'hello', 'two':'world'}; print(map1['one']); // 'hello' map1['one'] = 'world'; print(map1['one']); // 'world' }
5) 널 포인트 예외 관리하기
- 정의 : 널 포인트 예외(NPE:null point exception)를 코드 작성 시점에서 점검하는 것
- 널 포인트 예외(NPE:null point exception) : 객체가 null이어서 발생하는 오류
(1) 널 허용과 널 불허
- 널 허용, 널 불허 설정(기본값 : 널 불허)
// int int a1 = 10; // null 불허 int? a2 = 10; // null 허용 testFun() { a1 = null; // 오류 a2 = null; }
// string String str1 = null; // 오류 String? str1 = null; // class clear User{ } User user1 = null; // 오류 User? user2 = null;
(2) 널 불허 변수의 초기화
- 탑/클래스 내부(초기화 필수), 함수 내부(가능)
int a1; // 오류(초기화 해야됨) class User { int a1; // 오류(초기화 해야됨) } testFun() { int a1; // 성공(초기화 하지 않아도 됨) a1 = null; // 오류 }
- 함수 내부(사용하기 전 반드시 값 대입해주어야 함)
testFun() { int a1; print(a1 + 10); // 오류 int a2; a2 = 10; print(a2 + 10); // 성공 }
(3) var 타입의 널 안정성
- var 타입의 널 안정성(널 불가 : 타입 유추)
main() { var a1 = 10; // int var a2 = null; // dynamic var a3; // dynamic var? a4 = null; // 오류 }
int no1 = 10; // 널 불허 int? no2; // 널 허용 var a1 = no1; // int로 결정 var a1 = no2; // int?로 결정 testFun() { a1 = 20; a1 = null; // 널 불허 변수에 널을 대입해서 오류 a2 = 20; a2 = "hello"; // int? 타입에 문자열을 대입해서 오류 a2 = null; }
(4) dynamic 타입의 널 안정성
- dynamic 타입의 널 안정성(널 허용 : 모든 값 허용)
dynamic a1 = 10; dynamic a2; dynamic? a3; testFun() { a1 = null; a2 = null; a3 = null; }
(5) 널 안정성과 형 변환 - ?, as
- int? > int {널 허용[Nullable] > 널 불허[NonNull]}
int a1 = 10; int? a2 = 10; main() { a1 = a2; // 오류 a2 = a1; // 성공 }
- 명시적 형 변환
int a1 = 10; int? a2 = 20; main() { a1 = a2 as int; print("a1: $a1, a2: $a2"); // a1: 20, a2:20 }
(6) 초기화를 미루는 연산자 - late
- late(초기화 미루기)
int a1; // 컴파일 오류 late int a2; // 성공
late int a2; // 성공 main() { print('${a2 + 10}'); // 오류 a2 = 10; print('${a2 + 10}'); // 성공 }
6) 널 안정성 연산자
(1) 널 판단 - !
- null시 런 타임 오류 발생
int? a1 = 20; main() { a1!; a1 = null; a1!; // 런 타임 오류 }
int? some(arg) { if ( arg == 10 ) { return 0; } else { return null; } } main() { int a = some(10)!; print('a : $a'); // a : 0 int b = some(20)!; // some() 함수가 널을 반환하므로 런 타임 오류 print('b : $b'); }
(2) 널 허용 객체의 접근 - ?. / ?[]
- isEmpty - ?
String? str = "hello"; main() { str.isEmpty; // 오류 str?.isEmpty; }
- isEven - ?
main() { int? no1 = 10; bool? result1 = no1?.isEven; print('result 1 : $result1'); // true no1 = null; bool? result2 = no1?.isEven; print('result 2 : $result2'); // null }
- 널 리스트 접근할 때 - ?[]
main() { List<int>? list = [10, 20, 30]; print('list[0] : ${list?[0]}'); // 10 list = null; print('list[0] : ${list?[0]}'); // null }
(3) Null이 아닌 값만을 대입할 때 - ??=
- Null이 아닌 값만을 대입할 때 - ??=
main() { int? data3; data3 ??= 10; print('data3 : $data3'); // 10 data3 ??= null; print('data3 : $data3'); // 10(Null이라 대입 안됨) }
(4) Null인 값을 대체할 때 - ??
- Null인 값을 대체할 때 - ??
String? data4 = 'hello'; String? result = data4 ?? 'world'; // hello print('result : $result'); data4 = null; result = data4 ?? 'world'; // world print('result : $result');
댓글남기기