변수 초기화
var firstName = "Darren"; // var로 선언시 type infer됨
String lastName = "Kwon"; // 직접 타이핑 가능
미할당시
main() {
int? num;
print(num); // null
}
plugin 사용
import "dart:io";
main() {
stdout.write("Enter your name: ");
String? name = stdin.readLineSync();
print("Hello, $name!");
}
dart의 Primitive type들 (int, double, String, bool, dynamic)
main() {
// dart의 기본 타입 : int, double, String, bool, dynamic
int a = 100;
var b = 200; // type infer
print("$a, $b");
double c = 3.14;
var d = 1.14; // type infer
String e = 'Hello';
var f = 'World'; // type infer
bool g = true;
var h = false; // type infer
dynamic i = 100; // runtime에 타입이 정의됨.
i = "Hello"; // dynamic은 형이 다르게 할당할 수 있음
}
dynamic 타입의 런타임 타입 출력
main() {
dynamic a = 5;
print(a.runtimeType); // int
a = "string";
print(a.runtimeType); // String
}
raw string
main() {
String s = r'hello \n wow .... \t hehkekekke'; // raw string은 \n과 같은 이스케이프도 문자 처리함
print(s);
}
type conversion
// assert : https://dart.dev/guides/language/language-tour#assert
// assert는 디버깅 함수이다. 조건식이 거짓인 경우 오류 메시지를 출력한다.
// flutter 에선 개발 모드일 때, 일반 dart일 땐 dart --enable-asserts [path] 꼴로 실행해야 함
main() {
// String -> int
var one = int.parse('1');
assert(one == 1, 'one is not int type');
// String -> double
var float = double.parse('1.1');
assert(float == 1.1, 'float is not double type');
// int -> String
String str = 123.toString();
assert(str == '123', 'str is not string type');
// double -> String
String str2 = 1.141592.toStringAsFixed(2); // 소수점 2자리 절삭
assert(str2 == '1.14', 'str2 is not string type');
}
constant
main() {
const num = 0;
const a = true;
const b = 'string';
num = 5; // Constant variables can't be assigned a value.
print(num.runtimeType); // int
print(a.runtimeType); // bool
print(b.runtimeType); // String
}
operator : 우리가 관습적으로 사용하는게 다 된다.
main() {
int a = 1 + 2; // 3
a = a - 2; // 1
a++; // 2
++a; // 3
print(a == 3);
print(a != 3);
print(a > 3);
print(a < 3);
print(a >= 3);
}
null aware operator (?. ?? ??=)
// javascript
const a = {name: "darren"}
const b = a?.age ?? null // b는 null이 된다.
// dart에서도 같은 문법이 가능
int number = n?.num ?? 0;
var number = null;
print(number ??= 100); // number가 null이므로 100할당
print(number);
ternary operator
main() {
int n = 100;
n > 100 ? print('n is greater than 100') : print('n is less than or equal to 100');
}
type checking
main() {
var x = 100;
print(x is int); // true
print(x is String); // false
}
conditional statement : 너무 직관적이고 우리가 사용하는 그대로이다.
main() {
var a = 100;
if (a > 1000) {
print("wow");
} else if (a > 100) {
print("amazing");
} else {
print("should prin there");
}
}
switch statement
main() {
var a = 100;
switch (a) {
case 101:
print("impossible");
break;
case 100:
print("should print here");
break;
default:
print("impossible");
}
}
for loop
main() {
for (var i = 0; i < 3; i++) {
print(i);
}
for (var j in [10, 11, 12]) {
print(j);
}
for (var i = 0; i < 10; i++) {
if (i % 2 == 0) continue;
print(i);
}
[100, 101, 102].forEach((element) {
print(element);
});
}
while
main() {
int num = 0;
while (num < 3) {
print(num);
num++;
}
}
collections: list, set, map
main() {
List<int> list = [1, 2, 3];
List<dynamic> dynamicList = [1, 2, "he"];
List<int> constantList = const [1, 2]; // unmodifiable list. 즉, 변경 불가능한 list
var list2 = list; // reference 참조
var deppcopiedList = [...list]; // shallow copy
list2.add(4);
print(list); // list2에 추가했음에도 원본 변형. [1, 2, 3, 4]
print(deppcopiedList); // 다른 참조값이므로 원본 유지 [1, 2, 3]
}
main() {
Set<int> a = {1, 2, 3, 4, 3, 2, 1};
print(a); // 중복이 제거된 {1, 2, 3, 4}
var b = a; // reference 참조
var c = {...a}; // shallow copy
b.add(5);
print(a); // 원본도 변경됨 {1, 2, 3, 4, 5}
print(c); // 다른 reference 참조이므로 그대로 {1, 2, 3, 4}
}
main() {
Map<String, int> map = {"one": 1, "two": 2};
print(map['one']);
var copiedMap = map; // reference 참조
var newMap = {...map}; // shallow copy
copiedMap.clear(); // 싹 다 지우기
print(map); // 원본에도 영향
print(newMap); // 다른 reference 참조로 변화 없음 {one: 1, two: 2}
}
List에 대해서 좀 더 알아보자
void main() {
List a = [1, 2, 3, 4, 5, 6];
print(a.first);
print(a.last);
print(a.isEmpty);
print(a.isNotEmpty);
print(a.length);
print(a.reversed); // ReversedListIterable
a.add(7); // 하나만 넣기
a.addAll([8, 9, 10]); // 배열 넣기
a.remove(1); // 제거
print(a);
}
void main() {
List members = [
{'id': 0, 'name': 'darren'},
{'id': 1, 'name': 'anold'}
];
List numbers = [10, 20, 30, 40];
var zeroMember = members.firstWhere((member) => member['id'] == 0); // 원소 찾기
print(zeroMember);
var oneMember = members.indexWhere((member) => member['id'] == 1); // index 반환
print(oneMember);
var number = numbers.indexOf(30); // 30의 index 반환
print(number);
var hasTen = numbers.contains(10); // 10이 있는지 여부
print(hasTen);
}
map의 update가 독특하다
void main() {
Map items = {
"brain": "coding",
"phone": "iPhone"
};
items.update("shoes", (prev){return "wow";}, ifAbsent: () {return "you don't have shoes";});
print(items);
}
function
main() {
print(square.runtimeType); // (dynamic) => int. 함수의 타입도 찍어볼 수 있다.
print(printSomething.runtimeType); // (dynamic) => void
int result = addTwo(square(2));
printSomething(result);
}
int square(var num) {
return num * num;
}
int addTwo(int a) => a + 2; // arrow function이 가능하다.
void printSomething(var msg) => print(msg);
named parameters ({})와 optional parameters ([])
1. 일반적으로 우리가 쓰는 건 positional parameters다. 위치에 기반하기 때문이다.
2. 위치가 아닌 이름으로 구별하고 싶다면 named parameters를 사용하면 된다.
3. optional parameters는 positional parameters이면서도 단순히 옵셔널하게끔 만들 수 있다.
4. named parameters와 positional optional parameters 둘 다 사용하면 optional이라 기본값 지정 혹은 null handling이 필요.
main() {
sum(1, 2);
sum2(a: 1, b: 2); // named parameters
sum3(1, b: 2);
sum4(1); // positional optional parameters
}
int sum(int a, int b) => a + b;
int sum2({int a = 0, int b = 0}) =>
a + b; // named parameters는 optional이다. 따라서 기본값을 지정하거니 null handling이 필요.
int sum3(int a, {int b = 0}) => a + b; // 부분적으로 named parameters를 사용할 수 있다.
int sum4(int a, [int b = 0]) => a + b; // positional optional parameters
exception과 try/catch/finally
// Exception 던지기
int shouldGreaterThanZero(int val) {
if (val > 0) {
return val;
} else {
throw Exception('value should greater than zero');
}
}
// try/catch/finally
void verifyValue(var val) {
var verifiedValue;
try {
verifiedValue = shouldGreaterThanZero(val);
} catch (e) {
print("error occured: $e");
} finally {
print(verifiedValue);
}
}
final와 const
final : 런타임에 값이 지정이 되어도 상관 없음.
const : 컴파일타임에 값이 꼭 지정되어야 한다. -> 빌드 타임에 값이 정해져 있어야지, 런타임 돈 이후에 알게 되는 값은 안된다.
공통점 : 둘 다 상수라서 초기화 이후 변경이 불가능함.
main() {
final name = 'test';
final String name2 = "wow";
const name3 = "ama";
const String name4 = "ddd";
final now = new DateTime.now(); // 런타임에 할당되어 괜찮으니 에러가 아님
const now2 = new DateTime.now(); // 컴파일 시점에 알수가 없음. DateTime이 돌아야 알 것 아니냐. 그래서 에러임
}
enum
enum Status {
loading,
fetched,
done,
error,
}
main() {
Status status = Status.loading;
switch (status) {
case Status.loading:
print('로딩중');
break;
case Status.fetched:
print('페칭중');
break;
default:
print('불가능');
}
}
'Programming Language > 🎯 Dart' 카테고리의 다른 글
null safety (0) | 2022.01.03 |
---|