[Dart] 기본문법

래림·2023년 5월 7일

Flutter

목록 보기
3/7

이번 플젝은 flutter로 개발하기로 해서 dart를 공부하고 있습니다.
강의 들으면서 공부한 내용을 이해한대로 정리해보겠습니다.

dart의 enrty point, ;

main함수이다. main함수는 꼭 있어야 한다.
dart에서는 세미콜론 필수!! 세미콜론은 자동으로 추가되지 않는다.

변수선언

두가지가 가능하다.
1. var를 이용해 변수 선언 : 함수나 메소드 내부에 지역변수를 선언할 때 사용
2.명시적으로 타입 지정 : class에서 변수나 property를 선언할 때 타입 지정

void main() {
 var name="래림";
 String city="seoul";
}

dynamic

dynamic type을 이용하면 뭐든 될 수 있다.

void main() {
 var something;
  something=12;
  something="what";
}


string임을 확인한다면 위 사진과 같이 많은 string 기능을 사용할 수 있다.

final과 const

final
상수 선언 시 final 키워드를 이용한다. String (타입)은 생략 가능하다.

void main() {
final String name="래림";
}

const
값을 할당하고 변경할 수 없다는 점은 final과 같다. 그러나 const는 compile time에 값을 알고있어야 한다.

비교
사용자나 api를 통해 값을 받아와야 해서 comeplie time에 값을 모르는 상황이라면 final을 사용해야한다. 그러나 최대 인원 수 같은 정해진 값은 const를 사용한다.

자료형 신기한거

String, bool은 생각나는 그거다. 그런데 int, double은 num이라는 class를 상속받는게 신기했다.

List

if(giveMeFive){numbers.add(5)};
위의 코드를 아래처럼 할 수도 있다. 신기하다. 아래 코드가 더 좋은지는 사실 써봐야 알거같다..더 헷갈릴수도..아니 내가 뭘 모를수도..또 내가 잘못을..

void main() {
  var giveMeFive=true;
  List<int> numbers = [
    12,
    13,
    14,
    if(giveMeFive) 5,
  ];
 
  print(numbers);
}

collectoin For
와 이런게되네

void main() {
  var oldFriends = ['rarim', 'sun'];
  var newFriends = [
    'minsun',
    'minsu',
    'suji',
    for (var friend in oldFriends) "love $friend"
  ];

  print(newFriends);
}

실행결과

[minsun, minsu, suji, love rarim, love sun]

Maps

kotlin의 map과 같아보이는데, dart는 key에 String말고 다른게 들어갈 수 있다.

void main() {
  Map<List<int>,bool> player={
    
   [1,2,3,4]:true,
  };//최상위 type은 Object이다.

}

dart에서는 object형태를 만들 때 다음과 같이 하는걸 추천하지 않는다고 한다. 대신 class형태를 사용하는걸 추천한다고 한다. (class를 이용하는게 더 많은 기능을 사용할 수 있어서 라고 한다.)

void main() {
  List<Map<String, Object>> players = [
    {'name': 'rarim', 'xp': 11231231.123},
    {'name': 'rarim', 'xp': 11231231.123}
  ];
}

Sets

set은 집합의 개념이다. 중복은 허용이 안된다. List를 정의할 땐 [] 대괄호를 썼지만 set은 {} 중괄호 쓰면 된다.

void main() {
  var numbers={1,2,3,4};
  numbers.add(1);
  numbers.add(2);
  print(numbers);
}

화살표 함수

함수 body가 한줄이면 화살표를 사용해서 바로 리턴할 수 있다.

void sayHello(String name)=>
  print('hello $name nice to meet you');

num plus(num a, num b)=> a+b;

void main() {
  sayHello('민정');
}

parameter

positional parameter
함수 호출 시 정의된 함수에서의 인자 순서대로 입력한다. 이런 경우엔, 함수의 원형을 모르면 파라미터를 입력하기 힘들 수 있다. 그 대안으로 named parameter가 있다.

sayHello('minjung',19,"su");

named parameter
함수 호출 시 파라미터의 순서를 지키지 않는 대신, 이름을 입력해야한다.
만약 인자의 개수가 부족한 경우 (사용자가 실수로 name파라미터를 전달하지 않은 경우)를 대비해, default로 값을 지정하거나 required키워드를 이용할 수 있다.
required로 지정하면 파라미터가 null일때 컴파일되지 않는다.
default value를 지정하면 호출할 때 파라미터를 주지 않아도 default value가 적용된다.

String sayHello({
  required String name, 
  required int age,
  required String country}) {
  return "Hello $name, you are $age, and you come from $country";
}

void main() {
  print(sayHello(
    name: 'minjung', 
    age: 19, 
    country: "su"
  ));
}

Optional Positional Parameters
파라미터의 default값을 지정해서 optional로 만들기는 다음과 같이 할 수 있다.

String sayHello(
  String name, 
  int age,
  [String? country='seoul']) {
  return "Hello $name, you are $age, and you come from $country";
}

void main() {
 var results=sayHello('rarim',12);
  print(results);
}

?? operator

left ?? right
위와같은 코드가 있으면 left가 null이 아닐땐 left, left가 null이면 Right가 실행된다.

String capitalizeName(String? name)=>name?.toUpperCase() ?? 'ANOAN';
void main() {
 print(capitalizeName('rarim'));
 print(capitalizeName(null));
  
}

??=
??=라는 문법이 있다. 아래 코드와 같이 쓰인다면, name이 null이면 "rarim"을 할당하라는 뜻이다.


void main() {
 String? name;
  name??= 'rarim';
  
}

typedef

typedef를 이용하면 데이터 자료형을 alias할 수 있다.

typedef ListOfInts = List<int>// 이 자료형을 alias할 수 있다.

예시를 보면, 아래와 같이 쓸 수 있다.

typedef ListOfInts = List<int>;
ListOfInts reverseListOfNumbers(ListOfInts list){
  var reversed = list.reversed;
  return reversed.toList();
}

void main() {
  print(reverseListOfNumbers([1,2,3]));
  
}

이 문법을 이용해 typedef UserInfo = Map<String,String>같이 쓸 수 있지만, 이러한 구조화된 자료형은 class를 이용하는게 더 낫다고 한다.

class, constructors

class와 생성자는 다음과 같이 만들 수 있다. class를 인스턴스화 할땐 new 키워드를 생략할 수 있다.

class Player {
  late final String name;
  late int xp;
  
  Player(String name, int xp){
   this.name=name;
    this.xp=xp;
  }
  
  void sayHello(){
    print("Hi my name is $name");
  }

}


void main() {
  var player=Player("nico",1500);
 player.sayHello();
    var player2=Player("lynn",3500);
 player2.sayHello();
}

위의 코드를 좀 더 축약하면, 다음과 같이 작성할 수 있다. late키워드를 지우고, 생성자는 Player(this.name, this.xp); 이렇게 한줄로 쓸 수 있다.

class Player {
  final String name;
  int xp;
  
  Player(this.name, this.xp);
  
  void sayHello(){
    print("Hi my name is $name");
  }

}


void main() {
  var player=Player("nico",1500);
 player.sayHello();
    var player2=Player("lynn",3500);
 player2.sayHello();
}

Named Constructor

아래와 같이 : (콜론)을 이용해 argument와 property를 일대일 초기화 하는 생성자를 만들 수 있다.

class Player {
  final String name;
  int xp;
  String team;
  int age;

  Player(
      {required this.name,
      required this.xp,
      required this.team,
      required this.age});
  Player.createBluePlayer({
    required String name,
    required int age,
  })  : this.age = age,
        this.name = name,
        this.team = 'blue',
        this.xp = 0;
  
  Player.createRedPlayer(String name, int age) : 
  this.age=age,
  this.name=name,
  this.team="red",
  this.xp=0;

  void sayHello() {
    print("Hi my name is $name");
  }
}

void main() {
var bluePlayer = Player.createBluePlayer(
name:"nico",
  age:12
);
  var redPlayer = Player.createRedPlayer(
"minji",13
);
}

Cascade Notation

main함수에서 set을 할 때 ,rarim.name="이름" 이런 코드를 써서 한다. dart에서는 ..(점 두개)를 이용해 코드를 다음과 같이 줄일 수 있다.

class Player {
  String name;
  int xp;
  String team;

Player({required this.name, required this.xp, required this.team});

  void sayHello() {
    print("Hi my name is $name");
  }
}

void main() {
 var rarim=Player(name:'rarim',xp:1200,team:'red');
  rarim.name='ajs';
  rarim.xp;
  rarim.team='blue';
  
  ..name="name"
  ..xp=1212
  ..team='blue';
  
}

아래와 같이 다른 변수에 할당할 수도 있다.

void main() {
 var rarim=Player(name:'rarim',xp:1200,team:'red');
 var potato=rarim
  ..name='ajs'
  ..xp=1212
  ..team='blue'
  ..sayHello();
}

Enums

red, blue를 String으로 정의하면 타자를 치다가 실수를 할 수도 있다. 다음과 같이 Team이라는 enum을 정의하고, 개발자들의 선택의 폭을 줄여서 실수를 방지할 수 있다.

enum Team {red, blue}

class Player {
  String name;
  int xp;
  Team team;

Player({required this.name, required this.xp, required this.team});

  void sayHello() {
    print("Hi my name is $name");
  }
}

void main() {
 var rarim=Player(name:'rarim',xp:1200,team:Team.red);
 var potato=rarim
  ..name='ajs'
  ..xp=1212
  ..team=Team.blue
  ..sayHello();
}

Abstract Classes

추상화 클래스는 다른 클래스들이 직접 구현해야하는 메소드들을 모아놓은 blueprint이다. abstract클래스에 선언된 메소드들을 자식클래스에서 구현을 강제한다.

Mixins

생성자가 없는 class를 의미한다.
extend가 아니라 with 키워드를 사용한다. with를 사용하면 단순히 mixin 내부의 프로퍼티와 메소드들을 가져온다. 부모 클래스가 되는것이 아니다.

class String{
  final double strengthLevel = 1500.99;
}

class QuickRunner{
  void runQuick(){
    print("ruuuuun!");
  }
}

class Tall {
  final double height = 1.99;
}

enum Team {blue,red}


class Player with String, QuickRunner,Tall{
//이렇게 사용
}

참고한 강의

0개의 댓글