Flutter 알아둬야할 문법
Flutter는 Dart라는 언어를 사용한다. 개발 언어가 다들 비슷하지만 Dart만의 문법은 뭐가 있는지 알아보는 시간을 가져보자.
enum
enum은 몇 가지 값을 가지는 고유한 데이터 유형을 나타내는 데 사용된다. enum은 일반적으로 열거형 또는 열거형 상수라고도한다.
예를 들어, 간단한 색상 enum을 정의해 보자.
enum Color {
red,
green,
blue,
}
이제 우리는 Color
enum을 사용하여 다른 코드 부분에서 이러한 값 중 하나를 참조할 수 있다.
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');
}
}
코드에서는 Color enum 값을 변수 color에 할당했다.
?, ?., !, ??, ??=
?
Dart 언어에서 ?
기호는 nullable 타입을 표현하기 위해 사용된다. nullable 타입은 해당 변수 또는 객체가 null 값을 허용하는 타입을 말한다.
예를 들어, 아래 코드에서 name
변수는 String?
타입으로 선언된다. ?
기호가 타입 이름 뒤에 붙어 있으므로 name
변수는 null 값을 포함할 수 있다.
String? name = null;
?.
?.
연산자를 사용하여 nullable 타입의 프로퍼티나 메소드에 접근할 수 있다. 이 연산자는 변수가 null 일 경우에는 null 을 반환하고, null 이 아닐 경우에는 해당 프로퍼티나 메소드를 호출한다.
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'
위 코드에서 person
변수가 null로 초기화된다. person?.name
을 호출하면 null 값을 반환하고, person?.sayHello()
를 호출하면 null을 반환한다. 그러나 person
변수가 Person
객체로 초기화 된 후 name
프로퍼티를 설정하고 sayHello()
메소드를 호출하면 “Hello, my name is John Doe” 라는 문자열이 출력된다.
!
!
기호는 null 값을 허용하지 않는 non-nullable 타입으로 변환하기 위해 사용된다. 이를 non-null 단언 연산자라고도 한다.
어떤 경우에는 null 값이 발생할 가능성이 있지만 해당 변수가 null 이 아님을 개발자가 확신할 때 !
를 사용하여 null 값을 허용하지 않는 타입으로 강제 변환할 수 있다.
String? name = null;
String nonNullableName = name!; // throws an error
위 코드에서 name
변수는 nullable String 타입으로 선언된다. 그러나 !
기호를 사용하여 null 값을 허용하지 않는 타입인 String 으로 강제 변환하려고 시도한다. 하지만 name
변수가 null 이므로 이 코드는 런타임 에러를 발생시킨다.
따라서 !
기호는 개발자가 null 값이 아님을 확신할 때만 사용해야 하며, null 값이 발생할 가능성이 있는 경우에는 ?
기호와 조합하여 null 체크를 수행하는 것이 좋다.
??
??
연산자는 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
skip, take
Dart의 Iterable 클래스에 포함된 두 가지 메소드이다.
Iterable 클래스는 반복 가능한 컬렉션 데이터 타입의 슈퍼 클래스로서, List, Set, Map 등 여러 클래스에서 구현되고 있다.
skip
skip()
메소드는 컬렉션에서 지정된 개수의 요소를 건너뛴 후, 남은 요소들로 구성된 새로운 컬렉션을 반환한다. skip()
메소드는 다음과 같은 구문으로 사용할 수 있다.
Iterable<T> skip(int count)
여기서 T
는 컬렉션의 요소 타입을 나타낸다. count
는 건너뛸 요소의 개수를 나타낸다. 예를 들어, 아래 코드에서는 list 컬렉션에서 처음 3개의 요소를 건너뛰고 남은 요소들로 구성된 새로운 컬렉션을 생성한다.
var list = [1, 2, 3, 4, 5];
var newList = list.skip(3); // [4, 5]
take
take()
메소드는 컬렉션에서 지정된 개수만큼의 요소를 선택하여 새로운 컬렉션을 반환한다. take()
메소드는 다음과 같은 구문으로 사용할 수 있다.
Iterable<T> take(int count)
여기서 count
는 선택할 요소의 개수를 나타낸다. 예를 들어, 아래 코드에서는 list 컬렉션에서 처음 3개의 요소만 선택하여 새로운 컬렉션을 생성한다.
var list = [1, 2, 3, 4, 5];
var newList = list.take(3); // [1, 2, 3]
skip()
과 take()
메소드는 두 가지 메소드를 함께 사용하여 컬렉션에서 지정된 범위의 요소들로 구성된 새로운 컬렉션을 생성할 수도 있다. 예를 들어, 아래 코드에서는 list 컬렉션에서 첫 번째부터 세 번째까지의 요소를 건너뛰고, 그 다음 2개의 요소를 선택하여 새로운 컬렉션을 생성한다.
var list = [1, 2, 3, 4, 5];
var newList = list.skip(3).take(2); // [4, 5]
getter, setter
Dart언어에서 getter
와 sette
r는 객체의 속성에 대한 값을 가져오거나 설정하는 메소드이다.
getter
getter
는 속성의 값을 가져오는 메소드이며, getter
메소드의 이름은 get
키워드와 함께 속성의 이름으로 지정된다. getter
는 메소드 호출이 아니라 일반적인 속성의 사용처럼 객체.속성
형태로 사용된다.
class Person {
String _name = '';
String get name => _name;
}
void main() {
Person person = Person();
person.name = 'Alice'; // Compile error!
print(person.name); // Output: ''
}
위의 코드에서, Person
클래스의 name
속성은 getter
메소드인 get name
으로 정의되어 있다. get name
메소드는 _name
필드를 반환한다. name
속성은 읽기 전용 속성으로, 값을 변경할 수 없다.
setter
setter
는 속성의 값을 설정하는 메소드이며, setter
메소드의 이름은 set
키워드와 함께 속성의 이름으로 지정된다. setter
는 =
연산자를 사용하여 속성에 값을 할당할 때 자동으로 호출된다.
class Person {
String _name = '';
set name(String name) => _name = name;
}
void main() {
Person person = Person();
person.name = 'Alice';
print(person.name); // Output: 'Alice'
}
위의 코드에서, Person
클래스의 name
속성은 setter
메소드인 set nam
e으로 정의되어 있다. set name
메소드는 name
매개변수로 전달된 값을 _name
필드에 할당한다. name
속성은 쓰기 전용 속성으로, 값을 가져올 수는 있지만 값을 변경할 수 없다.