(Flutter-기초 강의) 4. Dart 필수 문법 및 동작의 이해 (Class, Function, Sync/Async, Inheritance, Collections)

앞선 글에서 설명했듯이, Dart는 Flutter라는 Framework에서 사용하는 프로그래밍 언어이고, 이를 완벽히 알려면 학습에 많은 시간이 필요합니다. 따라서, 필요한건 그때그때 찾아보기로 하고, 오늘은 필수적으로 알고 가면 좋은 문법 및 동작에 대해 알려드리고자 합니다.

다트(Dart) 언어는 기본적인 프로그래밍 요소들을 이해하고 활용하는 데 있어 중요한 문법을 포함하고 있습니다. 다트 문법의 핵심 개념들을 예제와 함께 자세히 살펴봅시다.

Class (클래스)

정의

다트(Dart)에서의 클래스(Class)는 객체 지향 프로그래밍(OOP)의 핵심 요소 중 하나입니다. 클래스는 데이터와 해당 데이터를 다루는 메서드를 포함하는 구조체입니다.

클래스는 class 키워드를 사용하여 정의됩니다. 클래스 정의는 다음과 같은 구조를 갖춥니다

class class_name {
  // define member variable
  type variable_name;

  // constructor 
  class_name(arguments) {
    // Initialize code
  }

  // methods
  return_type method_name(arguments) {
    // implements code
  }
}

활용 및 예제

클래스는 객체를 생성하는 템플릿으로, 이를 이용하여 실제 데이터를 담은 인스턴스를 만들 수 있습니다.

class Person {
  String name;
  int age;

  Person(String name, int age) {
    this.name = name;
    this.age = age;
  }

  void introduce() {
    print('Hello, I am $name, $age years old.');
  }
}

void main() {
  var person = Person('Jason', 30); // Make instance with Person class.
  person.introduce(); // Call the method of the person instance.
}

결과

Person 클래스는 nameage를 저장하는 속성과 introduce() 메서드를 포함하고 있습니다. 클래스를 이용하여 person 객체를 생성하고, 해당 객체의 메서드를 호출하였습니다.

Hello, I am Jason, 30 years old.

Exited.

Function (함수)

함수란특정 작업을 수행하고 결과를 반환하는 기능을 수행합니다.

Dart에서 함수는 다른 프로그래밍 언어에서와 마찬가지로 특정한 작업을 수행하기 위해 사용됩니다.

함수는 코드의 재사용성을 촉진하고, 프로그램을 모듈화하여 가독성을 높이며, 코드를 구조화하는 데 도움이 됩니다.

활용 및 예제

기본적인 함수 선언
: a와 b를 더하는 함수를 선언합니다.

int add(int a, int b) {
  return a + b;
}

함수 호출하기
: 앞서 선언한 add 함수를 호출하고 결과값을 res 변수에 저장합니다.

void main() {
  int res = add(5, 3);
  print('add result: $res');
}

선택적 매개변수 (Optional parameters)
: 함수에 매개변수를 전달하는 방법은 두 가지 방법이 있는데

위치 기반 매개변수(Positioned Parameter)
: 매개변수를 순서대로 위치에 맞게 전달하는 것을 의미합니다. (보통 다른 언어에서도 많이 사용되는 방법)

int add(int a, int b) {
  return a + b;
}

void main() {
  int res = add(3, 5); // Positioned parameter를 이용한 함수 호출
  print('add result: $res');
}

이름 지정 매개변수(Named Parameter)
: 매개변수에 curly bracket {}을 이용하여 이름을 명시하여 전달하는 방식입니다.

void whoIs({String? name, int? age}) {
  print('name: $name, age: $age');
}

void main() {
  whoIs(age: 25, name: '예시'); // Named parameter를 이용한 함수 호출
}

Sync/Async (동기/비동기)

동기(Synchronous)

동기적인 작업은 순차적으로 진행되는 작업을 의미합니다.

코드가 위 에서부터 아래로 순서대로 실행되며, 한 작업이 완료될 때까지 다음 작업은 대기합니다.

Future, async/await 과 같은 키워드가 사용되지 않으면 모두 동기화 하여 진행됩니다.

예제 코드

void main() {
  print('Start');  // 1

  int res = add(3, 5);
  print('add result: $res');  // 2

  print('End');  // 3
}

int add(int a, int b) {
  return a + b;
}
Start
add result: 8
End

비동기(Asynchronous)

비동기 코드는 한 작업이 완료될 때까지 기다리지 않고, 계속 진행하여 다른 작업을 동시에 진행할 수 있습니다.

Dart에서 비동기 작업을 수행하는 가장 흔한 방법은 Futureasync/await을 사용하는 것입니다.

dart:async

비동기 작업은 일반적으로 파일 I/O, 네트워크 작업, 타이머 등과 같은 작업에서 사용됩니다.

예제
: dart:async library을 import하여 Future, async/await을 사용하여 구현하였습니다.

import 'dart:async';

void main() {
  print('Start'); // 1

  asyncPrint('Aaync work')
      .then((_) => print('Complete!')) // 4
      .catchError((error) => print('Error: $error'));

  print('End'); // 2
}

Future<void> asyncPrint(String msg) async {
  await Future.delayed(Duration(seconds: 2));
  print(msg);  // 1.5 or 3
}
Start
End
Aaync work
Complete!

Inheritance(상속)

Dart에서의 상속은 클래스 간의 관계를 설정하여 하위 클래스(sub class)가 상위 클래스(super class)의 특성과 기능을 이어받을 수 있게 해줍니다.

예제
: 상위 클래스(super class) Animal을 상속받은 하위 클래스(sub class)를 Instance화 하여, 두 class의 속성과 method를 를 모두 사용하는 예제입니다.

// Super class
class Animal {
  String name;
  int age;

  Animal(this.name, this.age);

  void run() {
    print('Animal is running.');
  }
}

// Sub class
class Dog extends Animal {
  String breed;

  Dog(String name, int age, this.breed) : super(name, age);

  void bark() {
    print('bow-wow!');
  }
}

void main() {
  // Sub class instance
  var myDog = Dog('Jason', 3, 'golden retriever');

  myDog.run(); // Super class method
  myDog.bark(); // Sub class method

  print('This dog is ${myDog.age} years old, breed is ${myDog.breed}.');
}
Animal is running.
bow-wow!
This dog is 3 years old, breed is golden retriever.


Dart에서 Collections(컬렉션)은 여러 개의 항목을 그룹화하여 저장하는 데 사용되는 데이터 구조를 말합니다.

Dart는 다양한 종류의 컬렉션을 제공합니다. 주요 컬렉션으로 List(리스트), Set(집합), Map(맵)이 있습니다.

List

List는 순서가 있는 항목들의 목록을 저장하는 컬렉션입니다. 항목은 인덱스를 통해 접근할 수 있습니다.

예제

void main() {
  var giveMeFive = true;
  List<int> numbers = [
    1,
    2,
    3,
    4,
    if (giveMeFive) 5, // collection if
  ];
  numbers.add(1);

  print("$numbers ${numbers.first}");

  var oldFriends = ["jin", "jamy"];
  var newFrieds = [
    "Kim",
    "Lee",
    "Han",
    for (var friend in oldFriends) "$friend", // collection for
  ];

  print(newFrieds);
}
[1, 2, 3, 4, 5, 1] 1
[Kim, Lee, Han, jin, jamy]

Set

Set은 중복된 항목을 허용하지 않는 컬렉션입니다.

순서가 없고 유일한 값을 저장합니다.

예제

void main() {
  // Empty set
  Set<String> fruits = {};

  // add items
  fruits.add('apple');
  fruits.add('banana');
  fruits.add('apple'); // not allow duplicated item

  print('fruits: $fruits');
}
fruits: {apple, banana}

Map

Map은 키-값 쌍(key-value pair)을 저장하는 컬렉션입니다.

각각의 값은 고유한 키에 매핑됩니다. (Python의 dict와 유사합니다.)

예제

main() {
  Map<String, Object> player = {
    'name': 'jason',
    'hp': 500,
    'mp': 200,
  };

  Map<String, List<int>> friendsNum = {
    'JIN': [1, 2, 3],
    'KIM': [4, 5, 6],
    'LEE': [7, 8, 9],
  };

  friendsNum.addAll({
    'COOL': [6, 7, 10, 11]
  });

  print(player);
  print(friendsNum);
}
{name: jason, hp: 500, mp: 200}
{JIN: [1, 2, 3], KIM: [4, 5, 6], LEE: [7, 8, 9], COOL: [6, 7, 10, 11]}

오늘은 간단하지만

Dart를 사용하면서 필수적으로 알아야하는 문법에 대해 알아보았습니다.

Leave a Comment