Dart 기본 문법 정리 (1)

데구르르·2023년 11월 29일
0

Flutter

목록 보기
1/17
post-thumbnail

플러터로 앱개발을 하기 위해 Dart를 배우면서 기본 문법을 정리한 공간이다. 객체지향 언어다 보니 자바와 비슷한 점이 많았다.

문법정리

main 함수에서부터 코드가 실행된다

C나 Java처럼 main 함수가 없다면 코드를 실행할 수 없다. 형식은 아래와 같다.

void main() {
	// 여기에 코드를 작성해주세요.
}

Variables (변수)

프로그램에서 값을 저장하고 참조하는 데에 사용되는 개념으로, 타입을 지정하고, 선언을 하고, 초기화를 해야 한다. Java에서는 변수 선언을 할 때 타입을 명시해줘야 하지만, Dart에서는 var를 사용해 변수에 타입을 지정하지 않아도 선언이 된다. 또한, 초기화를 나중에 하고 싶다면 late 키워드를 사용해야 컴파일 에러가 나지 않는다.

void main() {
  // 정수형 변수
  int number = 37;
  
  // 실수형 변수
  double pi = 3.14;
  
  // 불리언 변수
  bool isDartFun = true;
  
  // 문자열 변수
  String greeting = 'Hello, Dart!';
  
  // 리스트 변수
  List<int> numbers = [1, 2, 3, 4, 5];
  
  // 맵 변수
  Map<String, int> ages = {
    'Alice': 25,
    'Bob': 30,
    'Jessi': 35,
  };
  
  // 변수 값 변경
  number = 54;
  pi = 3.141592;
  isDartFun = false;
  greeting = 'Goodbye, Dart!';
  numbers.add(6);
  ages['Kelly'] = 40;
  
}

위의 변수들은 값을 변경할 수 있지만, constfinal이 사용된 변수는 한 번 값을 할당하면 값을 변경할 수 없다. final은 런타임 시점, const는 컴파일 시점에 값이 할당된다. 그러므로 런타임시점의 값을 상수로 받아야 하는 경우 final을 사용해야 한다. 이러한 경우는 잘 없기 때문에 대부분의 경우 const를 사용하자. (안 그러면 const로 바꾸라는 경고가 뜬다...😭)

class Person {
  late String name;

  void sayHello() {
    print('Hello, my name is $name');
  }
}

void main() {
  var person = Person();
  person.name = 'Alice';
  person.sayHello();
}
// 변수 선언과 초기화
var name = 'Bob';

// 변수 타입 지정
Object objName = 'Bob';

// 변수 타입 지정 (명시적으로)
String strName = 'Bob';

// final 변수 선언
final finalName = 'Bob';   // bad

// const 변수 선언
const bar = 1000000;
const double atm = 1.01325 * bar;
const baz = [];

void main() {
  print(name); // 'Bob' 출력
  print(objName); // 'Bob' 출력
  print(strName); // 'Bob' 출력
  print(finalName); // 'Bob' 출력
  print(baz); // [] 출력
}

Control Flow (제어문)

다른 언어와 마찬가지로 if/else, switch/case, while, do/while, for문을 사용한다.

void main() {
  // if-else 문: 조건에 따라 코드 실행 여부 결정
  int number = 42;
  if (number > 50) {
    print('number is greater than 50');
  } else {
    print('number is less than or equal to 50');
  }
  
  // switch-case 문: 다중 분기 처리
  String fruit = 'apple';
  switch (fruit) {
    case 'apple':
      print('This is an apple');
      break;
    case 'banana':
      print('This is a banana');
      break;
    default:
      print('This is not a fruit');
  }
  
  // for-in 문: 리스트나 맵의 모든 항목에 대해 반복
  List<int> numbers = [1, 2, 3, 4, 5];
  for (int number in numbers) {
    print(number);
  }
  
  // while 문: 조건이 참인 동안 코드 반복 실행
  int count = 0;
  while (count < 5) {
    print(count);
    count++;
  }
  
  // do-while 문: 코드를 최소한 한번 실행하고, 조건이 참인 동안 반복 실행
  int i = 0;
  do {
    print(i);
    i++;
  } while (i < 3);
}

Functions (함수)

특수한 경우를 제외하고 인수(넣어주는 값)와 반환하는 값의 타입을 지정해주는 것이 권장된다. 반환값이 없으면 함수 이름 앞에 void를 넣으면 된다.
간단한 함수는 =>(화살표) 단축 구문으로 만들 수도 있다.
Dart에서 함수는 일급 객체 (First Class Object)이기 때문에 함수를 다른 함수의 인수로 사용할 수도, 함수를 바로 변수의 값에 할당할 수 있다.

void main() {
    // 타입 지정된 함수
    int add(int a, int b) {
        return a + b;
    }

    // 화살표 함수
    int multiply(int a, int b) => a * b;

    // forEach()를 사용한 함수 인수와 익명 함수
    var numbers = [1, 2, 3, 4, 5];
    numbers.where((number) => number.isEven).forEach(print);
    
    // 두 수를 더하는 함수 호출
    int result = add(5, 3);
    print('5 + 3 = $result');
}

Operator (연산자)

수학 연산이나 논리 계산을 할 때 사용된다. 이 표에 있는것 말고도 많은 연산자가 있으니 더 알아보고 싶다면 dart 공식 사이트를 참고하자.

Data Type

다른 언어의 데이터 타입과 별 차이가 없다. Records, Runes정도가 몰랐던 데이터 타입이다. 자세한 내용은 공식 문서를 읽어보자.

void main() {
  // Numbers
  int a = 10;
  double b = 3.14;
  num c = 1;   // num은 int와 double의 상위 타입 - 둘 다 할당 가능
  print("Numbers:");
  print("a: $a, b: $b, c: $c");

  // Strings
  String name = "John";
  String greeting = 'Hello, $name!';
  String multiLine = '''
    This is a multi-line string.
    It can cover multiple lines.
    ''';
  print("\nStrings:");
  print("name: $name");
  print("greeting: $greeting");
  print("multiLine: $multiLine");

  // Booleans
  bool isTrue = true;
  bool isFalse = false;
  print("\nBooleans:");
  print("isTrue: $isTrue");
  print("isFalse: $isFalse");

  // Lists
  List<int> numbers = [1, 2, 3];
  List<String> fruits = ["apple", "banana", "orange"];
  print("\nLists:");
  print("numbers: $numbers");
  print("fruits: $fruits");

  // Sets
  Set<int> numberSet = {1, 2, 3};
  Set<String> fruitSet = {"apple", "banana", "orange"};
  print("\nSets:");
  print("numberSet: $numberSet");
  print("fruitSet: $fruitSet");

  // Maps
  Map<String, int> ages = {"John": 30, "Jane": 25};
  Map<String, String> colors = {"apple": "red", "banana": "yellow", "orange": "orange"};
  print("\nMaps:");
  print("ages: $ages");
  print("colors: $colors");

  // Runes
  Runes input = new Runes('\u{1f600}');
  String smiley = String.fromCharCodes(input);
  print("\nRunes:");
  print("smiley: $smiley");

  // Symbols
  Symbol s = #test;
  print("\nSymbols:");
  print(s);
}
  • Runes: 유니코드를 문자열로 나타내기 위해 사용된다. 이를 사용하면 유니코드로 된 기호와 이모티콘을 화면에 출력할 수 있다.

369 게임

위에서 배운 문법으로 간단한 369게임을 만들어보았다.

요구사항

  1. 4명의 플레이어 Player1, Player2, Player3, Player4가 참가한다.
  2. 플레이어는 차례대로 순서가 돌아가며, 30의 배수 순서에는 "ahh" 출력, 3의 배수는 "clap"을 출력, 10의 배수는 "rool"을 출력, 나머지 순서에는 순서의 숫자를 출력한다.
  3. 범위는 1부터 100까지로, 총 clap, rool, ahh의 총 개수를 출력하고, 플레이어별로 clap을 몇 번 했는지 출력하고, 가장 많은 clap을 한 플레이어를 출력한다.
  late var result;
  int clapCount = 0;
  int roolCount = 0;
  int ahhCount = 0;

  int player1Count = 0;
  int player2Count = 0;
  int player3Count = 0;
  int player4Count = 0;

우선 플레이어 별 clap개수를 세기 위한 변수를 선언하고 (playerNCount), 총 clap, rool, ahh개수를 세기 위한 변수를 선언했다. result는 각각의 플레이어가 출력하는 값이다. string일 수도, int일 수도 있기 때문에 선언하는 당시에는 var를 사용했다.

  for (int i = 1; i <= 100; i++ ) {
    if (i % 30 == 0) {
      result = "ahh";
      ahhCount++;
    } else if (i % 10 == 0) {
      result = "rool";
      roolCount++;
    } else if (i % 3 == 0) {
      result = "clap";
      clapCount++;
      if (i % 4 == 1) {
        player1Count++;
      } else if (i % 4 == 2) {
        player2Count++;
      } else if (i % 4 == 3) {
        player3Count++;
      } else {
        player4Count++;
      }
    } else {
      result = i;
    }
    print("Player ${((i - 1) % 4) + 1}: $result" );

  }

100번 369게임을 진행하는 코드이다. i는 순서를 의미하고, 이 순서가 30, 10, 3의 배수라면 특정한 값이 result의 값으로 할당된다. 어떤 수의 배수를 확인하려면 나머지 값이 0이면 된다. 30, 10, 3의 배수일 경우 각각 ahh, rool, clap의 개수를 올려주고, clap일 경우 어떤 플레이어의 순서에서 clap이 출력되는지 확인 후 그 플레이어의 count를 올려준다.

print("\nclap의 총 갯수: $clapCount");
print("rool의 총 갯수: $roolCount");
print("ahh의 총 갯수: $ahhCount");

print("\nPlayer 1: $player1Count");
print("Player 2: $player2Count");
print("Player 3: $player3Count");
print("Player 4: $player4Count");

List<int> numArray = [player1Count, player2Count, player3Count, player4Count];
int maxValue = find_max_value(numArray);

print("\n가장 많은 clap을 출력한 플레이어: Player $maxValue");

}

int find_max_value(List<int> numArray) {
int max = numArray[0];
int index = 1;
for (int i = 0; i < numArray.length; i++) {
    if (numArray[i] > max) {
      max = numArray[i];
      index = i + 1;
    }
}
return index;

ahh, rool, clap의 총 갯수를 출력하고, 각각의 플레이어들이 몇 번 clap을 출력했는지도 보여준다. 다음, playerCount들에 대한 리스트를 만들어 리스트 값 중에 최댓값을 구하는 함수(find_max_value)에 인자로 넣는다. find_max_value는 리스트의 첫번째 값부터 차례로 비교해 최댓값을 찾는다. index는 최댓값의 위치이며, 이를 리턴하면 어떤 플레이어가 clap을 가장 많이 출력했는지 알 수 있다.

find_max_value함수에서 reduce()를 쓰면 코드가 더 간략해질 수 있다. (자바스크립트에서 많이 사용되는 함수인데 Dart에서도 된다!)

int find_max_value(List<int> numArray) {
  int max = numArray.reduce((maximum, b) => a > b ? a : b);
  return numArray.indexOf(max) + 1;
}

전체 코드 링크

TIL

  1. 연산자 / vs. ~/: ~/를 사용해야 나눈 값이 정수형으로 리턴된다.
  2. Runes, Records 자료형
  3. reduce() 함수를 Dart에서도 사용할 수 있다.
profile
개발 기록

0개의 댓글