본문 바로가기
🖥 Programming/📱Flutter

[Flutter] Dart 기본 문법

by MinChan-Youn 2023. 10. 24.

안녕하세요~ 챠니입니다! :)

 

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

 

younminchan - Overview

안드로이드 2년차 개발자 •⚽️/🎤/🥁/🖥/🏃‍♂️/🚴‍♂️/🤟 TechBlog⬇️ minchanyoun.tistory.com - younminchan

github.com

 

 

'🖥 Programming > 📱Flutter' 카테고리의 다른 글

[Flutter] command not found: flutter 해결방법  (0) 2024.01.10