본문 바로가기
프로그램 개발해서 돈벌기/flutter

[flutter] 기초 문법 중 특이한 구문 (?, ?., !, ??, ??=)

by ubmuhan 2023. 5. 8.
반응형

enum

enum은 몇 가지 값을 가지는 고유한 데이터 유형을 나타내는 데 사용합니다. enum은 일반적으로 열거형 또는 열거형 상수라고도 부릅니다.

 

enum Color {
  red,
  green,
  blue,
}

void main() {
  Color color = Color.red;
  if (color == Color.green) {
    print('Green color');
  } else if (color == Color.red) {
    print('Red color');
  } else if (color == Color.blue) {
    print('Blue color');
  }
}

 

?

Dart 언어에서 ? 기호는 nullable 타입을 표현하기 위해 사용합니다. nullable 타입은 해당 변수 또는 객체가 null 값을 허용하는 타입을 말합니다.

 

예를 들어, 아래 코드에서 name 변수는 String? 타입으로 선언합니다. ? 기호가 타입 이름 뒤에 붙어 있으므로 name 변수는 null 값을 포함할 수 있습니다.

 

String? name = null;

 

?.

?. 연산자를 사용하여 nullable 타입의 프로퍼티나 메소드에 접근할 수 있다. 이 연산자는 변수가 null 일 경우에는 null 을 반환하고, null 이 아닐 경우에는 해당 프로퍼티나 메소드를 호출합니다.

 

person 변수가 null로 초기화됩니다. person?.name을 호출하면 null 값을 반환하고, person?.sayHello()를 호출하면 null을 반환합니다. 그러나 person 변수가 Person 객체로 초기화 된 후 name 프로퍼티를 설정하고 sayHello() 메소드를 호출하면 “Hello, my name is John Doe” 라는 문자열을 출력합니다.

 

class Person {
  String? name;
  int? age;
  
  void sayHello() {
    print('Hello, my name is $name');
  }
}

Person? person = null;

person?.name; // null
person?.sayHello(); // null

person = Person();
person?.name = 'John Doe';
person?.sayHello(); // 'Hello, my name is John Doe'

 

 

!

! 기호는 null 값을 허용하지 않는 non-nullable 타입으로 변환하기 위해 사용합니다. 이를 non-null 단언 연산자라고도 합니다.

 

어떤 경우에는 null 값이 발생할 가능성이 있지만 해당 변수가 null 이 아님을 개발자가 확신할 때 !를 사용하여 null 값을 허용하지 않는 타입으로 강제 변환할 수 있습니다.

 

name 변수는 nullable String 타입으로 선언합니다. 그러나 ! 기호를 사용하여 null 값을 허용하지 않는 타입인 String 으로 강제 변환하려고 시도할때 name 변수가 null 이므로 이 코드는 런타임 에러가 발생합니다.

 

따라서 ! 기호는 개발자가 null 값이 아님을 확신할 때만 사용해야 하며, null 값이 발생할 가능성이 있는 경우에는 ? 기호와 조합하여 null 체크를 수행하는 것이 좋습니다.

 

String? name = null;
String nonNullableName = name!; // throws an error

 

 

??

?? 연산자는 null 병합 연산자(null coalescing operator)라고도 불리며, 왼쪽 피연산자가 null이면 오른쪽 피연산자를 반환하고, 그렇지 않으면 왼쪽 피연산자를 반환한다.

 

예를 들어, 아래 코드에서 name 변수가 null 이므로, name 대신에 John Doe 문자열을 출력합니다.

 

String? name = null;
String defaultName = 'John Doe';
String myName = name ?? defaultName;
print(myName); // John Doe

 

??=

??= 연산자는 null 할당 연산자(null assignment operator)라고도 불리며, 왼쪽 피연산자가 null 이면 오른쪽 피연산자의 값을 할당하고, 그렇지 않으면 기존의 값을 유지합니다.

 

예를 들어, 아래 코드에서 name 변수가 null 이므로, John Doe 문자열이 name 변수에 할당됩니다.

 

String? name = null;
String defaultName = 'John Doe';
name ??= defaultName;
print(name); // John Doe

 

 

Dart의 Iterable 클래스에 포함된 두 가지 메소드는 skip과 take 입니다.

 

Iterable 클래스는 반복 가능한 컬렉션 데이터 타입의 슈퍼 클래스로서, List, Set, Map 등 여러 클래스에서 구현되어 있습니다.

 

skip

skip() 메소드는 컬렉션에서 지정된 개수의 요소를 건너뛴 후, 남은 요소들로 구성된 새로운 컬렉션을 반환합니다. skip() 메소드는 다음과 같은 구문으로 사용할 수 있습니다.

 

여기서 T는 컬렉션의 요소 타입을 나타냅니다. count는 건너뛸 요소의 개수를 나타냅니다. 예를 들어, 아래 코드에서는 list 컬렉션에서 처음 3개의 요소를 건너뛰고 남은 요소들로 구성된 새로운 컬렉션을 생성합니다.

Iterable<T> skip(int count)

var list = [1, 2, 3, 4, 5];
var newList = list.skip(3); // [4, 5]

 

take

take() 메소드는 컬렉션에서 지정된 개수만큼의 요소를 선택하여 새로운 컬렉션을 반환합니다. take() 메소드는 다음과 같은 구문으로 사용할 수 있습니다.

 

여기서 count는 선택할 요소의 개수를 나타냅니다. 예를 들어, 아래 코드에서는 list 컬렉션에서 처음 3개의 요소만 선택하여 새로운 컬렉션을 생성합니다.

 

skip() take() 메소드는 두 가지 메소드를 함께 사용하여 컬렉션에서 지정된 범위의 요소들로 구성된 새로운 컬렉션을 생성할 수도 있습니다. 예를 들어, 아래 코드에서는 list 컬렉션에서 첫 번째부터 세 번째까지의 요소를 건너뛰고, 그 다음 2개의 요소를 선택하여 새로운 컬렉션을 생성합니다.

 

Iterable<T> take(int count)

var list = [1, 2, 3, 4, 5];
var newList = list.take(3); // [1, 2, 3]

var list = [1, 2, 3, 4, 5];
var newList = list.skip(3).take(2); // [4, 5]

 

 

Dart언어에서 getter setter는 객체의 속성에 대한 값을 가져오거나 설정하는 메소드입니다.

 

getter

getter는 속성의 값을 가져오는 메소드이며, getter 메소드의 이름은 get 키워드와 함께 속성의 이름으로 지정됩니다. getter는 메소드 호출이 아니라 일반적인 속성의 사용처럼 객체.속성 형태로 사용됩니다.

 

Person 클래스의 name 속성은 getter 메소드인 get name으로 정의되어 있습니다. get name 메소드는 _name 필드를 반환합니다. name 속성은 읽기 전용 속성으로, 값을 변경할 수 없습니다.

 

class Person {
  String _name = '';
  String get name => _name;
}

void main() {
  Person person = Person();
  person.name = 'Alice'; // Compile error!
  print(person.name); // Output: ''
}

 

 

setter

setter는 속성의 값을 설정하는 메소드이며, setter 메소드의 이름은 set 키워드와 함께 속성의 이름으로 지정됩니다. setter = 연산자를 사용하여 속성에 값을 할당할 때 자동으로 호출됩니다.

 

Person 클래스의 name 속성은 setter 메소드인 set name으로 정의되어 있습니다. set name 메소드는 name 매개변수로 전달된 값을 _name 필드에 할당합니다. name 속성은 쓰기 전용 속성으로, 값을 가져올 수는 있지만 값을 변경할 수 없습니다.

 

class Person {
  String _name = '';
  set name(String name) => _name = name;
}

void main() {
  Person person = Person();
  person.name = 'Alice';
  print(person.name); // Output: 'Alice'
}

 

 

 

 
반응형

댓글