Dart, 연산자(Operators)
글. 수알치 오상문
다트는 다음 표에 나오는 연산자를 지원합니다.
(참조: 클래스 멤버 연산자 구현 operators as class members.)
구분 연산자
단항 접미형 | expr++ expr-- () [] . ?. |
단항 접두형 | -expr !expr ~expr ++expr --expr await expr |
곱셈, 나누기 나머지, | * / % ~/ |
더하기, 빼기 | + - |
쉬프트(밀기) | << >> >>> |
비트 AND | & |
비트 XOR | ^ |
비트 OR | | |
비교 및 형 검사 | >= > <= < as is is! |
상등 | == != |
논리 AND | && |
논리l OR | || |
왼쪽이 null 이면 오른쪽 선택 | ?? |
조건 연산자 | expr1 ? expr2 : expr3 |
종속 계단 표기(cascade) | .. ?.. |
대입(할당) | = *= /= += -= &= ^= 등등. |
경고: 연산자 우선순위는 상세 규격을 참조하세요. Dart language specification.
연산자를 이용하여 다음처럼 다양한 수식을 만들 수 있습니다.
a++
a + b
a = b
a == b
c ? a : b
a is T
연산자 표에서 윗 줄에 있는 연산자들의 우선 순위가 높습니다(특수한 경우는 제외). 나머지 연산자(%)는 논리 AND 연산자(&&)보다 우선 순위가 더 높습니다. 연산자 우선 순위 때문에 다음 두 코드는 동일하게 실행됩니다.
// 괄호는 읽기 좋게 해줍니다.
if ((n % i == 0) && (d % i == 0))
...
// 읽기 어렵지만, 위 문장과 같습니다.
if (n % i == 0 && d % i == 0)
...
경고: 두 개의 피연산자를 사용하는 연산자의 경우, 가장 왼쪽 피연산자가 사용 방법을 결정합니다. 예를 들어, Vector와 Point 객체가 있는 경우 aVector + aPoint는 Vector 더하기(+)를 사용합니다.
산술 연산자
+ | 더하기 |
– | 빼기 |
-수식 | 음수 |
* | 곱하기 |
/ | 나누기 (실수 결과) |
~/ | 나누기 (정수 결과) |
% | 나머지 |
예:
assert(2 + 3 == 5);
assert(2 - 3 == -1);
assert(2 * 3 == 6);
assert(5 / 2 == 2.5); // 결과는 double
assert(5 ~/ 2 == 2); // 결과는 int
assert(5 % 2 == 1); // 나머지
assert('5/2 = ${5 ~/ 2} r ${5 % 2}' == '5/2 = 2 r 1');
선위/후위형 증가/감소 연산자
++변수 | 변수 값을 1 증가한다. (수식에 사용되면 먼저 변수를 1 증가하고 수식에 사용됨) |
변수++ | 변수 값을 1 증가한다. (수식에 사용되면 먼저 수식에 사용하고 변수를 1 증가함) |
--변수 | 변수 값을 1 감소한다. (수식에 사용되면 먼저 변수를 1 감소하고 수식에 사용됨) |
변수-- | 변수 값을 1 감소한다. (수식에 사용되면 먼저 수식에 사용하고 변수를 1 감소함) |
예:
var a, b;
a = 0;
b = ++a; // 1 증가한 후에 수식에 사용
assert(a == b); // 1 == 1
a = 0;
b = a++; // b에 a를 사용한 후에 a를 1 증가함
assert(a != b); // 1 != 0
a = 0;
b = --a; // 1 감소한 후에 수식에 사용
assert(a == b); // -1 == -1
a = 0;
b = a--; // b에 a를 사용한 후에 a를 1 감소함
assert(a != b); // -1 != 0
상등/비교 연산자
== | 같으면 true |
!= | 다르면 true |
> | 왼쪽이 더 크면 true |
< | 왼쪽이 더 작으면 true |
>= | 왼쪽이 크거나 같으면 true |
<= | 왼쪽이 작거나 같으면 true |
두 객체 x, y가 같은 것을 표현하는지 비교하려면 == 연산자를 사용합니다. (만약 두 객체가 같은 객체인지 비교하려면 identical() 함수를 사용합니다.)
== 연산자는 다음처럼 동작합니다.
- x 또는 y가 모두 null이면 true를 돌려주고 하나만 null이면 false를 돌려줍니다.
- 메서드 호출(x. == (y))의 결과를 반환합니다. (== 연산자는 왼쪽 객체의 비교 기능을 호출합니다.)
예:
assert(2 == 2);
assert(2 != 3);
assert(3 > 2);
assert(2 < 3);
assert(3 >= 3);
assert(2 <= 3);
자료 형 검사 연산자
as | 형변환(Typecast), (라이브러리 접두어 지정에도 사용 library prefixes ) |
is | 객체가 지정한 형과 같으면 true |
is! | 객체가 지정한 형과 다르면 true |
객체 obj를 구현할 때 T를 인터페이스했다면 obj is T 결과는 true입니다. 그러므로 obj is Object 결과는 항상 true입니다.
예: // 형변환이 확실한 경우
(employee as Person).firstName = 'Bob';
만약 형변환 T가 확실하지 않으면 먼저 검사한 후에 처리합니다.
if (employee is Person) { // 형 검사
employee.firstName = 'Bob';
}
참고: 위 예제 코드가 완전히 동일하진 않습니다. employee가 null이거나 Person이 아니면 첫 번째 예제는 예외가 발생합니다.
할당/대입 연산자
= 연산자를 사용하여 값을 할당 할 수 있습니다. 할당 대상 변수가 null 인 경우에만 할당하려면 ??= 연산자를 사용합니다.
// a에 value 할당
a = value;
// b가 null인 경우에만 할당
b ??= value;
복합 대입 연산자는 다음과 같습니다.
= | –= | /= | %= | >>= | ^= |
+= | *= | ~/= | <<= | &= | |= |
복합 대인 연산자 동작은 다음처럼 이후어집니다.
연산자 op인 경우 | a op= b | a = a op b |
예: | a += b | a = a + b |
var a = 2;
a *= 3; // a = a * 3
assert(a == 6);
논리 연산자
!수식 | 수식의 논리값을 반대로 바꿉니다. true이면 false, false이면 true |
|| | 논리 OR (어느 한쪽이라도 true이면 true) |
&& | 논리 AND (양쪽이 true일 때만 true) |
if (!done && (col == 0 || col == 3)) {
// ...
}
비트 연산자
일반적으로 정수형 변수/값을 대상으로 비트 단위로 논리 연산을 하거나 밀어내기 연산을 합니다.
& | AND (양쪽 비트가 1이면 결과는 1) |
| | OR (한쪽 비트라도 1이면 결과는 1) |
^ | XOR (양쪽 비트가 같으면 0, 아니면 1) |
~수식 | 모든 비트를 대상으로 1이면 0, 0이면 1로 바꿈 |
<< | 왼쪽으로 비트를 밀어냄 |
>> | 오른쪽으로 비트를 밀어냄 |
final value = 0x22;
final bitmask = 0x0f;
assert((value & bitmask) == 0x02); // AND
assert((value & ~bitmask) == 0x20); // AND NOT
assert((value | bitmask) == 0x2f); // OR
assert((value ^ bitmask) == 0x2d); // XOR
assert((value << 4) == 0x220); // Shift left
assert((value >> 4) == 0x02); // Shift right
조건 연산자
조건 연산자는 if else 조건문의 단축형 연산자이며 다음 형식을 사용합니다.
조건식 ? 수식1 :수식2
조건식이 참이면 수식1이 선택되고 아니면 수식2가 선택되어 사용됩니다.
var visibility = isPublic ? 'public' : 'private';
유사한 연산자로는 ?? 연산자가 있습니다.
수식1 ?? 수식2
만약 수식1이 null이 아니면 수식1이 선택되고, null이면 수식2가 선택됩니다.
String playerName(String? name) => name ?? 'Guest'; // name이 null이면 'Guset' 선택
위 예제는 다른 방식으로 작성할 수 있지만 간결하진 않습니다.
// ?: 연산자 사용.
String playerName(String? name) => name != null ? name : 'Guest';
// 고전적인 if-else 문장 사용
String playerName(String? name) { if (name != null) { return name; } else { return 'Guest'; } }
종속 계단 표기(Cascade) 연산자
종속 계단 표기 연산자를(.. 그리고 ?..) 이용하면 동일한 객체에 대한 표기 작업을 간결하게 할 수 있습니다. 함수 호출 외에도 동일한 객체의 필드에 접근할 수 있습니다. 때로는 임시 변수 생성을 줄이고 효율적인 코드를 작성할 수 있습니다.
(참고: 엄격하게 구분하면 .. 표기는 연산자가 아니라 다트 문법입니다.)
다음 코드를 살펴보면,
var paint = Paint()
..color = Colors.black
..strokeCap = StrokeCap.round
..strokeWidth = 5.0;
생성자 Paint ()는 Paint 객체를 반환합니다. 종속형 계단 표기법을 따르는 코드는 반환될 수있는 모든 값을 무시하고 이 객체에 작동합니다.
앞 예제는 다음 코드와 같습니다.
var paint = Paint();
paint.color = Colors.black;
paint.strokeCap = StrokeCap.round;
paint.strokeWidth = 5.0;
객체가 null 가능성이 있으면 null 제외 표기(?..)를 사용합니다. ?..로 시작하면 null 객체에 대해 작업을 하지 않습니다.
querySelector('#confirm') // 객체 얻기
?..text = 'Confirm' // 그것의 멤버 사용, 단 null이면 작업 안함
..classes.add('important')
..onClick.listen((e) => window.alert('Confirmed!'));
버전 참고: ?.. 문법은 다트 2.12.부터 지원합니다. 이전 버전에서는 이렇게 사용합니다.
var button = querySelector('#confirm');
button?.text = 'Confirm';
button?.classes.add('important');
button?.onClick.listen((e) => window.alert('Confirmed!'));
또한 중첩된 계단 표기도 가능합니다.
final addressBook = (AddressBookBuilder()
..name = 'jenny'
..email = 'jenny@example.com'
..phone = (PhoneNumberBuilder()
..number = '415-555-0100'
..label = 'home')
.build())
.build();
그외 연산자
() | 함수 | 함수 호출 표현 |
[] | 리스트 접근 | 리스트 인덱스를 이용한 접근 |
. | 멤버 접근 | 객체의 멤버에 접근 |
?. | 조건 멤버 접근 | 접근 대상이 null이 아닌 경우에 멤버에 접근 |
., ?., .. 연산자 참고: Classes.
<이상>
'Dart' 카테고리의 다른 글
Dart, 디버깅 함수 assert() (0) | 2021.06.15 |
---|---|
Dart, 흐름 제어 if, for, while, do while, switch (0) | 2021.06.15 |
Dart, 함수 비교 테스트 (0) | 2021.06.15 |
Dart, 접근 범위와 클로저(closure) (0) | 2021.06.15 |
Dart, 이름없는 함수 (0) | 2021.06.15 |