안녕하세요~ 챠니입니다! :)
Dart에서 제공하는 개발문서를 기반으로 작성했습니다.
1. 문자열 보관 (String interpolation)
표현식: ${expression}
String | Result |
'${3 + 2}' | '5' |
'${"word".toUpperCase()}' | 'WORD' |
'$myObject' | The value of myObject.toString() |
2. Null관련 (Nullable variables)
Dart에서는 Null이 될 수 있다고 명시하지 않는 한 Null값을 가질 수 없음
int a = null; // INVALID.
int? a = null; // Valid.
int? a; // The initial value of a is null.
3. Null 인식 연산자 (Null-aware operators)
"??=" 의 의미: 변수가 현재 null인 경우에만 변수에 값을 할당하는 연산자
int? a; // = null
a ??= 3;
print(a); // <-- Prints 3.
a ??= 5;
print(a); // <-- Still prints 3.
"??" 의 의미: 표현식 값이 null이 아닐 경우 -> 왼쪽 표현식, null일 경우 -> 오른쪽 표현식을 반환
print(1 ?? 3); // <-- Prints 1.
print(null ?? 12); // <-- Prints 12.
4. 조건부 속석 액세스 (Conditional property access)
Null일 수 있는 객체의 속성이나 매서드에 대한 액세를 보호하려면 "?"를 표시
예시)
myObject?.someProperty
//위의 코드와 동일
(myObject != null) ? myObject.someProperty : null
//단일 표현식에서 여러 용도를 함께 연결 가능
myObject?.someProperty?.someMethod()
5. 컬렉션 리터럴 (Collection literals)
Dart에서 사용하는 컬렉션 종류 (List, Set, Map)
final aListOfStrings = ['one', 'two', 'three'];
final aSetOfStrings = {'one', 'two', 'three'};
final aMapOfStringsToInts = {
'one': 1,
'two': 2,
'three': 3,
};
final aListOfInts = <int>[];
final aSetOfInts = <int>{};
final aMapOfIntToDouble = <int, double>{};
final aListOfBaseType = <BaseType>[SubType(), SubType()];
6. 화살표 구문 (Arrow syntax)
Dart코드에서 "=>"의 의미: 오른쪽에 있는 표현식을 실행 및 해당 값을 반환하는 함수를 정의
예시1)
bool hasEmpty = aListOfStrings.any((s) {
return s.isEmpty;
});
예시2) - 예시1의 코드를 더 간단하게 작성
bool hasEmpty = aListOfStrings.any((s) => s.isEmpty);
7. 캐스케이드 (Cascades)
동일한 객체에 대한 일련의 작업을 수행하려면 계단식 배열(..)을 사용 (kotlin의 apply와 비슷한 개념)
예시1) 캐스케이드 적용 전
var button = querySelector('#confirm');
button?.text = 'Confirm';
button?.classes.add('important');
button?.onClick.listen((e) => window.alert('Confirmed!'));
button?.scrollIntoView();
예시2) 캐스케이드 적용 후
querySelector('#confirm')
?..text = 'Confirm'
..classes.add('important')
..onClick.listen((e) => window.alert('Confirmed!'))
..scrollIntoView();
8. Getters and Setters
속성에 대한 더 많은 제어가 필요할 때마다 Getter, Setter를 정의
class MyClass {
int _aProperty = 0;
int get aProperty => _aProperty;
set aProperty(int value) {
if (value >= 0) {
_aProperty = value;
}
}
}
class MyClass {
final List<int> _values = [];
void addValue(int value) {
_values.add(value);
}
// A computed property.
int get count {
return _values.length;
}
}
9. 선택적 위치 매개변수 (Optional positional parameters)
Dart에서 마지막에 대괄호("[]")를 사용하여 선택사항으로 만들 수 있음
아래코드처럼 a를 제외한 b~e까지는 선택적으로 사용할 수 있음
int sumUpToFive(int a, [int? b, int? c, int? d, int? e]) {
int sum = a;
if (b != null) sum += b;
if (c != null) sum += c;
if (d != null) sum += d;
if (e != null) sum += e;
return sum;
}
// ···
int total = sumUpToFive(1, 2);
int otherTotal = sumUpToFive(1, 2, 3, 4, 5);
//b~e까지의 변수의 초기값을 먼저 설정
int sumUpToFive(int a, [int b = 2, int c = 3, int d = 4, int e = 5]) {
// ···
}
// ···
int newTotal = sumUpToFive(1);
print(newTotal); // <-- prints 15
10. 명명된 매개변수(Named parameters)
매개변수 목록 끝에 중괄호 구문을 사용하여 이름이 있는 매개변수 정의 가능 (선택사항)
* 선택적 위치 매개변수(Optional positional parameters)와의 차이 (정확하지는 않음):
명명된 매개변수(Named parameters)는 선택적으로 변수명이 선언된 것을 사용할 수 있지만, 선택적 위치 매개변수는 이름이 없고 정해진 순서에 따라 사용하기 때문에 어떤 값에 정확히 사용하는지에 대한 부분을 알 수 없음...
즉. 명명된 매개변수를 사용하는것이, 이름이 정해진 매개변수를 사용할 수 있어서 그렇지 않나 싶다..
예시코드는 아래와 같다. middleName이라고 명명된 매개변수를 사용하는 모습
void printName(String firstName, String lastName, {String? middleName}) {
print('$firstName ${middleName ?? ''} $lastName');
}
// ···
printName('Dash', 'Dartisan');
printName('John', 'Smith', middleName: 'Who');
// Named arguments can be placed anywhere in the argument list
printName('John', middleName: 'Who', 'Smith');
void printName(String firstName, String lastName, {String middleName = ''}) {
print('$firstName $middleName $lastName');
}
11. 예외(Exceptions)
Dart코드에서 예외를 발생시키고 확인할 수 있음 (일반적인 언에서 사용하는 예외와 비슷함)
//try예외를 처리할 때 , on및 키워드를 사용
try {
breedMoreLlamas();
} on OutOfLlamasException {
// A specific exception
buyMoreLlamas();
} on Exception catch (e) {
// Anything else that is an exception
print('Unknown exception: $e');
} catch (e) {
// No specified type, handles all
print('Something really unknown: $e');
}
//예외를 완전히 처리할 수 없는 경우 rethrow키워드를 사용하여 예외를 전파
try {
breedMoreLlamas();
} catch (e) {
print('I was just trying to breed llamas!');
rethrow;
}
//예외 발생 여부에 관계없이 코드를 실행하려면 다음을 사용 - finally
try {
breedMoreLlamas();
} catch (e) {
// ... handle exception ...
} finally {
// Always clean up, even if an exception is thrown.
cleanLlamaStalls();
}
12. this 생성자에서 사용 (Using this in a constructor)
속성에 값을 할당하는 편리한 단축키 제공
//일반적인 사용
class MyColor {
int red;
int green;
int blue;
MyColor(this.red, this.green, this.blue);
}
final color = MyColor(80, 80, 128);
//명명된 매개변수에도 적용. 속성 이름은 매개변수의 이름
class MyColor {
...
MyColor({required this.red, required this.green, required this.blue});
}
final color = MyColor(red: 80, green: 80, blue: 80);
MyColor([this.red = 0, this.green = 0, this.blue = 0]);
// or
MyColor({this.red = 0, this.green = 0, this.blue = 0});
13. 초기화 목록 (Initializer lists)
생성잘를 구현할 때 생성자 본문이 실행되기 전에 몇 가지 설정을 수행하는 경우
초기화 목록에서 이 작업을 수행
Point.fromJson(Map<String, double> json)
: x = json['x']!,
y = json['y']! {
print('In Point.fromJson(): ($x, $y)');
}
14. 명명된 생성자(Named constructors)
Dart에서는 클래스가 여러 생성자를 가질 수 있도록 명명된 생성자를 지원
class Point {
double x, y;
Point(this.x, this.y);
Point.origin()
: x = 0,
y = 0;
}
//명명된 생성자를 사용하려면 전체 이름을 사용하여 호출
final myPoint = Point.origin();
15. 팩토리 생성자(Factory constructors)
하위 유형이나 null을 반환할 수 있는 생성자를 지원
class Square extends Shape {}
class Circle extends Shape {}
class Shape {
Shape();
factory Shape.fromTypeName(String typeName) {
if (typeName == 'square') return Square();
if (typeName == 'circle') return Circle();
throw ArgumentError('Unrecognized $typeName');
}
}
16. 생성자 리디렉션(Redirecting constructors)
constructors의 목적이 동일한 클래스의 다른 생성자로 redirection이 되는 경우도 있음.
class Automobile {
String make;
String model;
int mpg;
// The main constructor for this class.
Automobile(this.make, this.model, this.mpg);
// Delegates to the main constructor.
Automobile.hybrid(String make, String model) : this(make, model, 60);
// Delegates to a named constructor
Automobile.fancyHybrid() : this.hybrid('Futurecar', 'Mark 2');
}
17. Const 생성자
클래스가 절대 변경되지 않는 객체를 생성하는 경우, 객체를 컴파일 타임 상수로 만들 수 있음
class Recipe {
final List<String> ingredients;
final int calories;
final double milligramsOfSodium;
const Recipe(this.ingredients, this.calories, this.milligramsOfSodium);
}
* 반복 가능한 컬렉션(Iterable collections)
18. 컬렉션(Iterable)
Iterable: 순차적으로 액세스할 수 있는 요소의 컬렉션
//좋은 예시
Iterable<int> iterable = [1, 2, 3];
int value = iterable.elementAt(1);
//나쁜 예시
Iterable<int> iterable = [1, 2, 3];
int value = iterable[1];
18-1. 요소읽기(Reading elements)
* 1) for-in 루프 사용 예시코드
void main() {
const iterable = ['Salad', 'Popcorn', 'Toast'];
for (final element in iterable) {
print(element);
}
}
* 2) 처음과 마지막 사용
void main() {
Iterable<String> iterable = const ['Salad', 'Popcorn', 'Toast'];
print('The first element is ${iterable.first}');
print('The last element is ${iterable.last}');
}
* 3) firstWhere() 사용 [특정 조건을 만족하는 첫 번째 요소 찾기]
- 조건을 충족하는 결과값이 2개 이상이여도 1개만 출력
- singleWhere()보다는 firstWhere()이 보다 더 안전하지 않나 생각됨
String element = iterable.firstWhere((element) => element.length > 5);
* 4) singleWhere() 사용 [특정 조건을 만족하는 첫 번째 요소 찾기]
- 조건을 충족하는 조건이 없으면 에러
- 조건을 충족하는 결과값이 2개 이상이면 에러
items.singleWhere((item) => item.startsWith('M') && item.contains('a'));
18-2. 조건 확인(Checking conditions)
* any(), Every() 사용
- any(): 하나 이상의 요소가 조건을 만족하면 true를 반환
- every(): 모든 요소가 조건을 만족하면 true를 반환
items.any((item) => item.contains('a'))
items.every((item) => item.length >= 5))
// 예시)
if (items.any((item) => item.contains('Z'))) {
print('At least one item contains "Z"');
} else {
print('No item contains "Z"');
}
18-3. 필터링(Filtering)
* where() 사용
- takeWhile(): 조건을 충족하는 모든 요소를 포함
var numbers = const [1, -2, 3, 42].where((number) => number > 0);
* takeWhile(), skipWhile() 사용
- takeWhile(): 조건을 충족하는 요소 이전의 모든 요소를 포함
- takeWhile(): 조건을 만족하지 않는 첫 번째 요소를 포함하여 이후의 모든 요소를 포함
void main() {
const numbers = [1, 3, -2, 0, 4, 5];
var numbersUntilZero = numbers.takeWhile((number) => number != 0);
print('Numbers until 0: $numbersUntilZero');
//Numbers until 0: (1, 3, -2)
var numbersStartingAtZero = numbers.skipWhile((number) => number != 0);
print('Numbers starting at 0: $numbersStartingAtZero');
//Numbers starting at 0: (0, 4, 5)
}
18-4. 매핑(Mapping)
* Iterable 활용
Iterable<String> getNameAndAges(Iterable<User> users) {
return users.map((user) => '${user.name} is ${user.age}');
}
//예시
Iterable<EmailAddress> parseEmailAddresses(Iterable<String> strings) {
return strings.map((s) => EmailAddress(s));
}
bool anyInvalidEmailAddress(Iterable<EmailAddress> emails) {
return emails.any((email) => !isValidEmailAddress(email));
}
Iterable<EmailAddress> validEmailAddresses(Iterable<EmailAddress> emails) {
return emails.where((email) => isValidEmailAddress(email));
}
class EmailAddress {
final String address;
EmailAddress(this.address);
@override
bool operator ==(Object other) =>
identical(this, other) ||
other is EmailAddress &&
runtimeType == other.runtimeType &&
address == other.address;
@override
int get hashCode => address.hashCode;
@override
String toString() {
return 'EmailAddress{address: $address}';
}
}
질문 또는 궁굼한 부분은 댓글을 남겨주세요! 친절하게 답변드리겠습니다!
응원의 댓글은 저에게 큰 힘이 된답니다! :)
즐거운 하루되세요!
깃허브 보러 놀러오세요 👇 (맞팔환영)
https://github.com/younminchan
'🖥 Programming > 📱Flutter' 카테고리의 다른 글
[Flutter] command not found: flutter 해결방법 (0) | 2024.01.10 |
---|