Dart 기본 문법(1) - 변수와 데이터 타입 / 연산자(Operators)
Today I Learned (250624) 1-2.
1. 변수와 데이터 타입
변수
- 데이터를 저장하기 위한 공간 (데이터를 담는 상자)
- 데이터를 담는 상자인 변수에 데이터를 담고, 필요할 때 데이터를 꺼내서 사용
ㄴ 나이라는 이름 상자를 만들고, 그 상자에 30 이라는 데이터를 담는 느낌
- 변수에 데이터를 저장하면 컴퓨터 메모리 어딘가에 그 데이터가 저장됨
ㄴ 컴퓨터는 그 데이터를 저장하고 있다가 필요하다고 하면 변수 이름을 가지고 그 데이터를 찾아서 줌
- 상자에는 이름을 붙일 수 있음 (같은 이름의 데이터 상자 허용하지 않음)
변수의 종류: 프로그램 실행 중(런타임)에 값 변경 가능 여부에 따라 크게 2가지로 나뉨
1. 프로그램 실행 중에 값을 변경할 수 있는 변수
* [타입] [변수이름] = [값];
int age = 30; String name = 'Bob'; bool isStudent = true;
* var [변수이름] = [값];var name = 'Bob';
ㄴ 타입 추론 (Type Inference)을 해서, 타입을 쓰지 않는 경우도 있음
* 타입 추론 (Type Inference): 타입을 명시하지 않았을 때 변수에 넣은 값을 보고, 타입을 추론해주는 것
ㄴ 위와 같이 코드를 쓰면 name에 'Bob'이 할당된 것을 보고 name이 String 타입인 것을 추론함
2. 프로그램 실행 중에 값을 변경할 수 없는 변수: 상수(Constant)
* final [타입] [변수이름] = [값];
final firstCurrentTime = DateTime.now(); // 타입 명시하지 않은 경우 final DateTime secondCurrentTime = DateTime.now(); // 타입 명시한 경우
ㄴ 타입 추론이 가능하기 때문에 [타입] 생략 가능
ㄴ DateTime.now() 실행 시점의 현재 시간을 가져오는 코드
* const [변수이름] = [값];
const pi = 3.14159; // 타입 명시하지 않은 경우 const int age = 30; // 타입 명시한 경우
ㄴ 마찬가지로 타입 추론이 가능하기 때문에 [타입] 생략 가능
* final / const 1) 초기화 시점 2) 용도에 차이가 있음
1) 초기화 시점
- final 변수: 프로그램 실행(런타임) 시점
- const 변수: 컴파일 시점 / 그래서 const 변수를 컴파일 타임 상수라고 부르기도 함
2) 용도
- final 변수: 프로그램 실행 중에 값이 결정되는 경우 ex. 현재 시간
- const 변수: 프로그램 실행 전이든 실행 후든 상관없이 항상 값이 고정인 경우 ex. 원주율 (3.14xxx...)
* 변수의 값을 바꾸면 오류 발생 !!final String name = 'Bob'; name = 'Alice'; // Error: Can't assign to the final variable 'name'. const int age = 25; age = 30; // Error: Can't assign to the const variable 'age'.
3. late 변수
- 선언 후에 초기화되는 NonNullable한 변수
- 변수가 사용되는 시점에 초기화(지연 초기화)되는 변수
* late [타입] [변수이름];
late String name;
ㄴ late 변수는 [타입] 생략 불가능
* late 변수 사용 시기
1) 변수를 선언할 당시에 넣어줄 값을 아직 특정하기 어려운 경우
late String description; void main() { description = '설명입니다.'; print(description); // 설명입니다. }
ㄴ 선언할 때 넣어줄 값을 특정하기 어려울 때는 null을 쓰면 되지 않을까?
- 컴퓨터는 null을 싫어하기 때문에 최대한 null 사용 자제
- late 변수는 null을 허용하지 않으면서도 변수에 null을 넣어준 것과 비슷한 역할을 함
late String name; print(name); // Error: Late variable 'name' without initializer is definitely unassigned.
ㄴ 값을 넣지 않은 상태로 변수를 쓰면 오류 발생 ! - 그렇기 때문에 사용 전 무조건 값을 넣어야 함
2) 초기화 비용이 높은 변수가 지금 당장 필요하지는 않은 경우
int getTemperature(int temperature) { return temperature; } void main() { late int temperature = getTemperature(35); }
ㄴ main에 있는 temperature 변수가 사용되지 않았기 때문에 getTemperature(35)는 실행되지 않음
데이터 타입
- 타입은 프로그래밍 할 때 다루는 데이터의 형태
- 어떤 형태의 값을 다룰 것인지(데이터 타입을) 컴퓨터에게 알려줘야 함.
- 변수에 할당할 수 있는 값의 유형 (변수가 데이터를 담는 상자라면, 데이터 타입은 상자가 담을 수 있는 데이터의 형태)
* 데이터 타입 종류
1. 숫자형 (Numbers)
int : 정수(소수점이 없는 숫자) 유형 int [변수이름] = [값]; int a = 1; int b = -5;
double : 소수(소수점이 있는 숫자) 유형 double [변수 이름] = [값]; double a = 1.5; double b = 0.1234; * 값을 정수로 할당하면 자동으로 소수점 부여 double z = 1; // double z = 1.0 와 같아요. z += 2.5; print(z); // 3.5
num : 정수, 소수 등의 모든 숫자 유형으로 int와 double의 상위 클래스 Object > num > int / double num [변수 이름] = [값]; num a = 1; num b = 1.5; * int, double 모두를 포함하기 때문에, int, double 모두(정수/소수) 가능 num a = 1; a += 2.5; print(a); // 3.5
2. 문자형 (Strings)
String : 문자 유형 String [변수이름] = '문자'; / String [변수이름] = "문자"; (작은 따옴표, 큰 따옴표 모두 가능) String a = 'hello'; String b = "bye"; * 식별자는 $식별자 형태로, 표현식은 ${표현식} 형태로 만들면 문자열에 넣을 수 있음 String name = 'Bob'; print('Hello, my name is $name.'); // Hello, my name is Bob. print('Hello, my name is ${name.toUpperCase()}.'); // Hello, my name is BOB. * toUpperCase()는 문자열에 있는 모든 문자를 대문자로 변경함 * == 연산자를 통해 두 값이 같은지 판별 가능 String word = 'HELLO'; print('hello' == word.toLowerCase()); // true * toLowerCase()는 문자열에 있는 모든 문자를 소문자로 변경함 * + 연산자를 통해 2개 이상의 문자열을 합칠 수 있음 String prefix = 'Hello, '; String suffix = 'my name is Bob.'; print(prefix + suffix); // Hello, my name is Bob. * 작은 따옴표 3개 이어 붙인 형태(''')나 큰 따옴표를 3개 이어 붙인 형태(""")를 통해 여러 줄의 문자열도 만들 수 있음 String s1 = ''' 이렇게 하면 여러 줄의 문자열을 만들 수 있어요 ! '''; /* 이렇게 하면 여러 줄의 문자열을 만들 수 있어요 ! */ String s2 = """이것도 여러 줄의 문자열이랍니다 !"""; /* 이것도 여러 줄의 문자열이랍니다 ! */
3. 불리언형 (Booleans)
bool : 참(true) 또는 거짓(false)으로 판별할 수 있는 유형 bool [변수이름] = [값]; bool isTrue = true; bool isFalse = false;
null
- 값이 없다는 것을 컴퓨터에 알려주기 위해 사용
- null을 허용하는 변수 (Nullable한 변수)는 타입 뒤에 ?를 붙임
int a = 3;
int? b = null;
a는 int 뒤에 ?가 없기 때문에 NonNullable한 변수이고,
b는 int 뒤에 ?가 있기 때문에 Nullable한 변수이다.
- null을 허용하는 변수는 초기값이 설정되지 않으면 기본적으로 null을 가짐
int? nullableInt;
print(nullableInt); // null
nullableInt = 1;
print(nullableInt); // 1
nullableInt = null;
print(nullableInt); // null
int nonNullableInt;
print(nonNullableInt); // Error: Non-nullable variable 'nonNullableInt' must be assigned before it can be used.
- null을 허용하는 변수를 사용할 때는 항상 주의해야하고, 최대한 덜 쓰려고 노력해야함
ㄴ 컴퓨터가 null을 싫어하기 때문에 프로그램 실행중에 오류가 발생하기도 함.
ㄴ 상관 없이 null을 오류 없이 안전하게 쓰고 싶다면?
ㄴ ?. 연산자 사용
어떤 변수가 null이면 ?.이 포함한 표현식 전체가 null이 됨
String? name;
print(name?.length); // null
name = 'Bob';
print(name?.length); // 3
String? name; 까지만 있을 때는 name에 기본값으로 null이 들어가기 때문에
name?.length 가 null로 반환됨
하지만, name에 'Bob'을 넣어주면 더이상 name은 null이 아니기 때문에
name?. length가 null이 아닌 값이 반환됨
2. 연산자(Operators)
- 프로그램 내에서 데이터를 조작하거나 처리하기 위해 사용하는 기호 또는 키워드
- 수학적인 계산 뿐 아닌, 논리적인 비교, 데이터 조합 등 다양한 작업에 사용
* 연산자 종류
1. 산술 연산자 (Arithmetic Operators)
- 기본 연산 (덧셈, 뺄셈, 곱셈, 나눗셈, 나머지) 수행 시 사용
- 종류
+ : 두 개의 값을 더할 때 사용
int two = 2; int three = 3; print(two + three); // 5
- : 하나의 값에서 다른 하나의 값을 뺄 때 사용
int two = 2; int three = 3; print(three - two); // 1 print(two - three); // -1
* : 두 개의 값을 곱할 때 사용
int two = 2; int three = 3; print(two * three); // 6
/ : 하나의 값에서 다른 하나의 값을 나눌 때 사용 > 그 값을 반환함
int five = 5; int two = 2; print(five / two); // 2.5
~/ : 하나의 값에서 다른 하나의 값을 나눌 때 사용 > 정수 부분만 반환함
int five = 5; int two = 2; print(five ~/ two); // 2
% : 하나의 값에서 다른 하나의 값을 나누었을 때 나오는 나머지를 구할 때 사용
int six = 6; int four = 4; print(six % four); // 2
2. 비교 연산자 (Comparison Operators)
- 2개의 값을 비교할 때 사용
- 종류
== : 2개의 값이 같으면 true, 다르면 false를 반환
int a = 4; int b = 4; print(a == b); // true int c = 2; int d = 4; print(c == d); // false int? e = null; int? f = null; print(e == f); // true int? g = null; int? h = 2; print(g == h); // false
!= : 2개의 값이 다르면 true, 같으면 false 반환
int a = 2; int b = 4; print(a != b); // true int c = 4; int d = 4; print(c != d); // false int? e = null; int? f = 2; print(e != f); // true int? g = null; int? h = null; print(g != h); // false
> : > 기준으로 왼쪽에 있는 값이 오른쪽에 있는 값보다 크면 true, 작거나 같으면 false 반환
int a = 4; int b = 2; print(a > b); // true int c = 2; int d = 4; print(c > d); // false
< : < 기준으로 왼쪽에 있는 값이 오른쪽에 있는 값보다 작으면 true, 크거나 같으면 false 반환
int a = 2; int b = 4; print(a < b); // true int c = 4; int d = 2; print(c < d); // false
>= : >= 기준으로 왼쪽에 있는 값이 오른쪽에 있는 값보다 크거나 같으면 true, 작으면 false 반환
int a = 4; int b = 2; print(a >= b); // true int c = 3; int d = 3; print(c >= d); // true int e = 2; int f = 4; print(e >= f); // false
<= : <= 기준으로 왼쪽에 있는 값이 오른쪽에 있는 값보다 작거나 같으면 true, 크면 false 반환
int a = 2; int b = 4; print(a <= b); // true int c = 3; int d = 3; print(c <= d); // true int e = 4; int f = 2; print(e <= f); // false
3. 타입 체크 연산자 (Type Test Operators)
- 프로그램 실행 중 (런타임)에 타입을 검사할 때 사용
* 타입 체크 연산자의 종류
1) as : 타입을 변환(Type Casting)할 때 사용
- 형변환(Type Casting): 하나의 특정 타입으로 지정되어 있는 값을 다른 타입으로 바꾸는 것
int a = 2; print(a as double); // 2 String b = '2'; print(b as double); // TypeError 발생
ㄴ 확실하게 형변환이 가능할 때만 사용 가능
형변환이 불가능한 경우에 as를 사용하면 TypeError 발생
2) is : 특정 타입을 가지고 있는지 판별할 때 사용
int? a = 2; print(a is int); // true int? b = null; print(b is int); // false
3) is! : 특정 타입을 가지고 있지 않은지 판별할 때 사용 (is와 반대 개념)
int? a = null; print(a is! int); // true int? b = 2; print(b is! int); // false
4. 대입 연산자 (Assignment Operators)
- 값을 변수에 대입할 때 사용
* 대입 연산자 종류
= : = 기준으로 오른쪽 값을 왼쪽에 대입
int a = 2; print(a); // 2
??= : ??= 기준으로 왼쪽에 있는 것이 null 일 때 오른쪽 값을 대입
int? a = null; a ??= 2; print(a); // 2 int b = 3; b ??= 2; print(b); // 3
+= : += 기준으로 왼쪽에 있는 것과 오른쪽에 있는 것을 더해서 왼쪽에 대입
a += b 와 a = a + b 는 같은 의미
int a = 2; int b = 3; a += b; print(a); // 5
-= : -= 기준으로 왼쪽에 있는 것에서 오른쪽에 있는 것을 빼서 왼쪽에 대입
a -= b 와 a = a - b 는 같은 의미
int a = 3; int b = 2; a -= b; print(a); // 1
*= : *= 기준으로 왼쪽에 있는 것과 오른쪽에 있는 것을 곱해서 왼쪽에 대입
a *= b 와 a = a * b 는 같은 의미
int a = 2; int b = 3; a *= b; print(a); // 6
/= : /= 기준으로 왼쪽에 있는 것에서 오른쪽에 있는 것을 나눠서 왼쪽에 대입
a /= b 와 a = a / b 는 같은 의미
double a = 6; int b = 3; a /= b; print(a); // 2
~/= : ~/= 기준으로 왼쪽에 있는 것에서 오른쪽에 있는 것을 나누었을 때 나온 값의 정수 부분을 왼쪽에 대입
int a = 5; int b = 3; a ~/= b; print(a); // 1
%= : %= 기준으로 왼쪽에 있는 것에서 오른쪽에 있는 것을 나누었을 때 나온 나머지를 왼쪽에 대입
int a = 5; int b = 3; a %/= b; print(a); // 2
5. 논리 연산자 (Logical Operators)
- 참 또는 거짓으로 판별할 수 있는 표현식을 반전하거나 결합할 때 사용
* 논리 연산자 종류
1) ! : ! 기준으로 오른쪽에 있는 판별식을 반전함
bool a = true; print(!a); // 판별식을 반전해서 true가 false로 출력
2) || : || 기준으로 왼쪽 판별식과 오른쪽 판별식 중 하나라도 참이면 참을 반환하고, 모두 거짓이면 거짓을 반환
또는(or)과 같은 의미라고 생각
bool a = true; bool b = true; print(a || b); // true bool c = true; bool d = false; print(c || d); // true bool e = false; bool f = false; print(e || f); // false
3) && : && 기준으로 왼쪽 판별식과 오른쪽 판별식 모두 참이면 참을 반환하고, 하나라도 거짓이면 거짓을 반환해요.
그리고(and)와 같은 의미라고 생각
bool a = true; bool b = true; print(a && b); // true bool c = true; bool d = false; print(c && d); // false bool e = false; bool f = false; print(e && f); // false