Pattern

1. 논리 OR 패턴 A || B

하위 패턴 중 어느 하나라도 일치하면 매치됩니다. 모든 분기는 완전히 동일한 변수 집합을 정의해야 합니다.

enum Color { red, yellow, blue, green }
void main() {
  Color c = Color.red;
  bool primary = switch(c) {
    Color.red || Color.yellow || Color.blue => true,
    _ => false
  };
  print(primary); // true
}Code language: Dart (dart)

2. 논리 AND 패턴 A && B

두 하위 패턴이 모두 동시에 일치해야 하며, 하위 패턴끼리 동일한 이름의 변수를 바인딩할 수 없습니다.

void main() {
  switch((2, 3)) {
    // 컴파일 오류: 두 하위 패턴 모두 변수 b를 바인딩하여 변수명 충돌 발생
    // case (var a, var b) && (var b, var c): print("ok");
    case (var a, var b) && (>1, <5):
      print("a=$a,b=$b"); // a=2,b=3
  }
}Code language: Dart (dart)

여기서 (>1, <5) 는 첫 번째 숫자는 1보다 크고 두 번째 숫자는 5보다 작아야 한다는 조건입니다.

3. 관계 연산자 패턴 < > <= >= == !=

숫자 범위 판단에 사용하며, 보통 && 와 함께 범위 제한 용도로 활용합니다.

String asciiCharType(int charCode) {
  const space = 32, zero = 48, nine = 57;
  return switch(charCode) {
    < space => "제어 문자",
    == space => "공백",
    > space && < zero => "문장 부호",
    >= zero && <= nine => "숫자",
    _ => "기타"
  };
}
void main() {
  print(asciiCharType(50)); // 숫자
  print(asciiCharType(33)); // 문장 부호
}Code language: Dart (dart)

위 예시는 ASCII 코드를 활용해 제어 문자, 숫자, 기호 등을 분류합니다. switch에 전달하는 charCode 판단 규칙: 32 미만은 제어 문자, 32는 공백, 32 초과 48 미만은 문장 부호, 48 이상 57 이하는 숫자, 나머지는 기타로 구분합니다.

4. 강제 타입 변환 패턴 sub as Type

구조 분해 중 타입을 강제로 변환하며, 타입이 일치하지 않으면 런타임 예외를 발생시킵니다.

void main() {
  (num, Object) rec = (10, "hello");
  var (i as int, s as String) = rec;
  print(i + 5); // 15
  print(s.toUpperCase()); // HELLO
}Code language: Dart (dart)

이 예시에서 rec를 i, s로 분해하는데, rec 첫 요소가 정수가 아니거나 두 번째 요소가 문자열이 아닐 경우 예외가 발생합니다.

아래는 오류가 발생하는 예시입니다.

void main() {
  (num, Object) rec = (9.3, "hello");
  var (i as int, s as String) = rec;
  print(i + 5); // 15
  print(s.toUpperCase()); // HELLO
}Code language: Dart (dart)
D:\dartdemo\firstdart>dart run
Building package executable...
Built firstdart:firstdart.
Unhandled exception:
type 'double' is not a subtype of type 'int' in type cast
#0      main (file:///D:/dartdemo/firstdart/bin/firstdart.dart:3:10)
#1      _delayEntrypointInvocation.<anonymous closure> (dart:isolate-patch/isolate_patch.dart:314:19)
#2      _RawReceivePort._handleMessage (dart:isolate-patch/isolate_patch.dart:193:12)Code language: PHP (php)

5. Null 검사 패턴 sub?

값이 null이 아닐 때만 매치되며 내부 변수는 자동으로 Null 불허 타입으로 승격됩니다. null일 경우 매치가 실패하고 예외는 발생하지 않습니다.

void main() {
  String? str = "test";
  switch(str) {
    case var s?:
      print(s.length); // s는 null 불허 문자열, 출력 4
    case null:
      print("null 값");
  }
}Code language: Dart (dart)

6. Null 단정 패턴 sub!

값이 null이 아닐 때만 매치되며, 값이 null이면 즉시 런타임 예외를 던집니다.

void main() {
  List<String?> row = ["user", "bob"];
  switch(row) {
    case ["user", var name!]:
      print(name); // name은 null 불허 문자열
  }

  // 변수 구조 분해에서 사용
  (int?, int?) pos = (2, 3);
  var (x!, y!) = pos;
  print(x + y);
}Code language: Dart (dart)

var name! 분석

  • var name변수 패턴var 로 새로운 지역 변수 name 을 선언하고 매치 성공 시 값을 바인딩합니다;
  • !후위 Null 단정 패턴 — 현재 값이null이 아니어야 함을 강제하며 null일 경우 런타임 오류가 발생합니다.

합쳐진 의미:var name! 은 새 변수 name을 생성하는 동시에 값이 null이 아님을 강제로 보장합니다.

7. 상수 패턴

리터럴, 명명 상수, const 생성자, const 컬렉션 모두 상수 패턴에 해당하며 값이 동일하면 매치됩니다.

지원 타입:숫자, 문자열, 불리언, 명명 상수, const 객체 / 리스트

void main() {
  const target = 10;
  int num = 10;
  switch(num) {
    case 1: print("일");
    case target: print("상수 10과 일치");
    case const [1,2]: print("상수 리스트");
    default: print("기타");
  }
}Code language: Dart (dart)

실행 결과

상수 10과 일치

8. 변수 패턴 var x / int x / final x

매치 성공 시 새로운 지역 변수에 값을 바인딩하며 타입을 명시하면 동시에 타입 검증을 진행합니다.

void main() {
  switch((99, "dart")) {
    case (int a, String b):
      print("$a $b"); // 99 dart
    case (int a, int b):
      print("두 숫자 값");
  }
}Code language: Dart (dart)

9. 식별자 패턴

사용 문맥에 따라 세 가지 동작으로 나뉩니다:

  1. 선언 문맥 var (a,b):새 변수 생성
  2. 할당 문맥 (a,b) = val:기존 변수 덮어쓰기
  3. switch 매치 문맥:상수로 취급(_ 제외)
void main() {
  const c = 5;
  int val = 2;
  switch(val) {
    case c: print("상수 c와 일치");
    default: print("매치되지 않음"); // 이 줄 실행
  }
}
Code language: Dart (dart)

10. 괄호 패턴 (subPattern)

패턴 연산자 우선순위를 조절해 ||&& 의 연산 순서를 구분합니다.

void main() {
  bool x = true, y = true, z = false;
  bool test = switch(true) {
    (x || y) && z => true,
    _ => false
  };
  print(test); // false
}
Code language: Dart (dart)

11. 리스트 패턴

List 객체에 매치하며 위치 순서로 요소를 분해합니다. ... rest 연산자로 임의 개수의 나머지 요소를 캡처할 수 있습니다.

1. 기본 리스트 매치
void main() {
  const a = "a", b = "b";
  var arr = ["a", "b"];
  switch(arr) {
    case [a, b]: print("매치 성공");
    default: print("매치 실패");
  }
}Code language: Dart (dart)
2. rest로 나머지 요소 캡처
void main() {
  var [a, b, ...rest, c, d] = [1,2,3,4,5,6,7];
  print("$a $b $rest $c $d"); // 1 2 [3, 4, 5] 6 7
}
Code language: Dart (dart)
D:\dartdemo\firstdart>dart run
Building package executable...
Built firstdart:firstdart.
1 2 [3, 4, 5] 6 7Code language: CSS (css)

12. Map 패턴 {"key": subP}

Map 객체에 매치하고 지정한 키만 검증합니다. 대상 키가 없으면 StateError 가 발생하며 언급하지 않은 추가 키는 무시합니다.

void main() {
  var data = {"user": ["Lily", 13]};
  if(data case {"user": [String name, int age]}) {
    print("$name $age"); //Lily 13
  }
}Code language: JavaScript (javascript)

13. 레코드 패턴

두 종류:위치 레코드 (p1,p2) , 명명 레코드 (k:p1,k2:p2)

:var 축약 문법을 지원해 중복되는 필드명을 생략할 수 있습니다.

void main() {
  // 위치 레코드 분해
  var (name, age) = ("Doug", 25);
  // 명명 필드 축약 분해
  final (:name, :age) = (name: "Tom", age: 18);
}
Code language: JavaScript (javascript)

14. 객체 패턴 Class(prop: p)

지정한 타입의 객체에 매치하고 Getter 속성을 분해하며 :var 축약 문법을 사용할 수 있습니다.

class Point {
  final int x, y;
  Point(this.x, this.y);
}

void main() {
  Point p = Point(10, 20);
  var Point(:x, :y) = p;
  print("$x $y");
}
Code language: JavaScript (javascript)

15. 와일드카드 패턴 _

모든 값에 매치하되 변수를 바인딩하지 않으며, 자리 표시자나 타입만 검증하고 값을 꺼내지 않을 때 사용합니다.

void main() {
  var arr = [1,2,3];
  var [_, mid, _] = arr;
  print(mid); // 2

  switch((10, "abc")) {
    case (int _, String _):
      print("타입 매치 성공");
  }
}Code language: JavaScript (javascript)

Pattern

답글 남기기

이메일 주소는 공개되지 않습니다. 필수 필드는 *로 표시됩니다