티스토리 뷰

728x90
반응형

 

 

노마드 코더 Dart 시작하기 영상을 보고 정리한 내용입니다.

https://nomadcoders.co/dart-for-beginners/lectures/4124

 

All Courses – 노마드 코더 Nomad Coders

초급부터 고급까지! 니꼬쌤과 함께 풀스택으로 성장하세요!

nomadcoders.co

 

 

 

 

 

 

환경 : VSCode

Ubuntu에서 VSCode 설치

https://code.visualstudio.com/download

 

Download Visual Studio Code - Mac, Linux, Windows

Visual Studio Code is free and available on your favorite platform - Linux, macOS, and Windows. Download Visual Studio Code to experience a redefined code editor, optimized for building and debugging modern web and cloud applications.

code.visualstudio.com

 

.deb 파일 다운로드 후 터미널에서 아래 명령어 실행

sudo dpkg -i code_1.91.0-1719861592_amd64.deb

 

반응형

 

 

마지막으로 Dart SDK 설치.

sudo apt-get update && sudo apt-get install apt-transport-https
wget -qO- https://dl-ssl.google.com/linux/linux_signing_key.pub   | sudo gpg  --dearmor -o /usr/share/keyrings/dart.gpg
echo 'deb [signed-by=/usr/share/keyrings/dart.gpg arch=amd64] https://storage.googleapis.com/download.dartlang.org/linux/debian stable main'   | sudo tee /etc/apt/sources.list.d/dart_stable.list
sudo apt-get update && sudo apt-get install dart

 

 

설치 후 터미널에서 "code" 입력하면 VSCode가 실행됩니다.

code

 

 

VSCode 실행한 후 Extensions에서 Dart, Flutter 검색 후 설치

 

 

 

- 데이터 타입: var, dynamic, String, int,...

Dart에서는 var(Dart에서 알아서 타입확인), String(변수타입설정), dynamic(다이나믹)을 사용합니다.

void main() {
  // 메소드 내부에 지역변수를 선언할 때는 var를 사용
  // class에서 변수나 property를 선언할 때에는 타입을 지정
  var name = "a"; // 선언할 때 문자열로 선언했다면 문자열로만 수정 가능
  // name = 12; // error!
  print(name);

  var name2; // 선언할 때 아무것도 정의하지 않았다면 타입은 dynamic이므로 모든 타입으로 수정 가능
  name2 = "a";
  name2 = true;
  name2 = 12;
  print(name2);

  dynamic name3 =
      "a"; // dynamic으로 선언했다면 계속 수정 가능. 하지만 dynamic은 정말 필요할때만 쓰는것이 좋음.
  name3 = 12;
  name3 = true;
  print(name3);

  if (name is String) {
    // 이 블럭 안에서는 name이 String이라는 것을 앎.
    print(name.compareTo("12")); // String 관련 메소드 사용 가능
  }

  if (name2 is int) {
    // 이 블럭 안에서는 name2가 int이라는 것을 앎
    print(name2.isOdd); // int 관련 메소드 사용 가능
  }

}

 

 

 

- null safety

기본적으로 모든 변수는 non-nullable이라, 눈으로 봤을 때는 개발자가 null 값을 참조할 수 없도록 되어있는데.

null safety는 어떤 변수, 혹은 데이터가 null이 될 수 있음을 명시하는 것을 말합니다.

 

bool isEmpty(String string) => string.length == 0;

void main() {
  isEmpty(Null); // Null을 참조할수 없게 했는데 참조하여 에러가 남.

  // --> dart에서는 어떤 변수가 null이 될 수 있음을 정확히 표시해야함
  String? nico =
      'nico'; // 이경우에서 nico가 null도, string도 될 수 있다고 하려면 String 뒤에 물음표를 넣어주면 됨.
  nico = null; // 물음표를 넣어주면 에러가 사라진다.
  if (nico != null) {
    print(nico.isNotEmpty);
  }
  // 위의 코드는 아래와 같음
  print(nico?.isNotEmpty); // nico가 null이 아니라면 isNotEmpy 속성을 달라고 요청함.
}

 

 

 

- late

late는 final이나 var 앞에 붙여줄 수 있는 수식어로, 초기데이터 없이 변수를 선언할 수 있게 해줍니다.

void main() {
  // late는 final이나 var 앞에 붙여줄 수 있는 수식어로, 초기데이터 없이 변수를 선언할 수 있게 해줌.
  late final String name;

  print(name); // name안에 아무것도 없기 때문에 오류남.

  // do something, go to api // API에서 데이터를 받아 변수에 넣어줌
  name = 'nico';
  print(name); //여기에서는 오류 안남
}

 

 

- complie-time constant

  dart에서 const는 compile-time constant를 만들어줍니다.
  compile-time constant란? const는 compile-time에 알고 있는 값이어야 한다는 것입니다.
  앱스토어에 앱을 올리기 전에 이미 알고 있는 값이라는 것입니다.

  // dart에서 const는 compile-time constant를 만들어줍니다.
  // compile-time constant란? const는 compile-time에 알고 있는 값이어야 한다는 것입니다.
  // 앱스토어에 앱을 올리기 전에 이미 알고 있는 값이라는 것입니다.
  const api_key = "121212";
  // 아래는 compile-time constant가 아닙니다.
  const API = fetchApi(); // 컴파일될때 모르는 값이며 이건 const가 아니라 final이 맞습니다.

 

 

 

728x90

- Lists

void main() {
  int age = 12; // int는 extends num 을 받은 class
  double money = 69.99; // double도 extends num을 받은 class
  num x = 12; // 따라서 num은 int, double 둘다 사용 가능
  x = 1.1;

  var numbers = [
    1,
    2,
    3,
    4,
  ]; // List<int> numbers
  List<int> numbers2 = [
    1,
    2,
    3,
    4,
  ]; // 위와 같음
  numbers.add(1);
  numbers2.add(1);
  print(numbers);
  print(numbers2);
}

 

 

 

조건에 따라 값을 추가하여 넣을 수도 있습니다.

  var giveMeFive = true;

  var numbers = [
    1,
    2,
    3,
    4,
    if (giveMeFive) 5, // giveMeFive가 true라면 List에 5를 추가
  ];
  print(numbers);

 

 

- String Interpolation

문자열 삽입하는 방법입니다.

void main() {
  var name = "nico";
  var age = 10;
  var greeting =
      "Hello everyone, my name is ${name} and I'm ${age + 2} years old.";
  print(greeting);
}

 

 

 

리스트 안에서도 동일하게 문자열을 합쳐 사용할 수 있습니다.

 

 

void main() {
  var oldFriends = ['nico', 'lynn'];
  var newFriends = [
    'lewis',
    'ralph',
    'darren',
    for (var friend in oldFriends) "♥ $friend",
  ];
  print(newFriends);
}

 

[lewis, ralph, darren, ♥ nico, ♥ lynn]

 

 

함수를 사용할 때 파라미터가 전달되어오지 않는다면 default value를 사용하는 방법이 있고,

'required'라고 명시해주는 방법이 있습니다.

 

첫번째로 default value를 사용하는 방법입니다.

String sayHello(
    {String name = 'anon', int age = 99, String country = 'wakanda'}) {
  return "Hello $name, you are $age, and you come from $country";
}

void main() {
  print(sayHello(
    age: 12,
    country: 'cuba',
    // name: 'nico',
  ));
}

 

 

위와 같이 name에 주석처리를 하고 파라미터를 전송한 경우

출력 결과는 다음과 같습니다. default value를 읽어 출력합니다.

Hello anon, you are 12, and you come from cuba

 

두번째로 'required'를 명시해주는 방법은. 무조건 파라미터를 명시해주어야 하는 조건입니다.

파라미터 중 하나라도 전달되지 않으면 에러가 발생합니다.

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( // 에러발생
    age: 12,
    country: 'cuba',
    // name: 'nico',
  ));
}

 

 

 

- QQ Operator

name != null ? name.toUpperCase() : 'ANON' 과

name.toUpperCase() ?? 'ANON'은 같은 결과를 리턴하는 코드입니다.

String capitalizeName(String? name) {
  name != null ? name.toUpperCase() : 'ANON';
  name.toUpperCase() ?? 'ANON';
}

 

 

다음과 같이 사용할 수 있습니다.

 

String capitalizeName(String? name) => name?.toUpperCase() ?? 'ANON';

void main() {
  capitalizeName('nico');
}

 

 

??= 이 오퍼레이션은, 정의가 되지않았다면 값을 넣으라는 의미입니다.

출력결과로는 'nico'가 출력되며, 이미 'nico'라는 값이 들어갔기 때문에 name ??= 'another' 부분에서 warning 경고가 뜹니다.

 

void main() {
  String? name;
  name ??= 'nico';
  name ??= 'another';
  print(name);
}

 

 

 

- Class

가장 중요한 세션인 class입니다. class내에서 선언하는 property는 타입을 사용해서 선언해야합니다.

 

class Player {
  String name = 'nico'; // class에서 property를 선언할 때는 타입을 사용해서 선언.
  int xp = 1500;

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

void main() {
  var player = Player();
  print(player.name);
  player.name = 'hahaha';
  print(player.name);
  player.sayHello();
}

 

 

Player를 생성할때 값을 지정해서 생성하는 것도 가능합니다.

생성자 함수를 만들어주면 됩니다.

 

class Player {
  late String name; // class에서 property를 선언할 때는 타입을 사용해서 선언.
  late int xp;

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

  // 생성자의 이름은 class의 이름과 같아야 합니다.
  Player(String name, int xp) {
    this.name = name;
    this.xp = xp;
  }
}

void main() {
  var player = Player('nico', 1500);
  player.sayHello();
}

 

 

위의 생성자 함수는 아래와 같이 더 간단하게 작성가능합니다.

  Player(String name, int xp) {
    this.name = name;
    this.xp = xp;
  }
  // 위와 동일한 내용의 생성자함수 
  Player(this.name, this.xp);

 

 

아래와 같은 형식으로 property를 지정하게끔 설정하여 만들수도 있습니다.

Named Constructors라고 합니다.

Player를 Red팀과 Blue팀으로 나누어 저장하도록 합니다.

class Player {
  late String name; // class에서 property를 선언할 때는 타입을 사용해서 선언.
  late int xp;
  late String team;
  late int age;

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

  // 생성자의 이름은 class의 이름과 같아야 합니다.
  Player({
    required this.name,
    required this.xp,
  });

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

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

void main() {
  var player1 = Player.createBluePlayer(name: 'blue_nico', age: 24);
  var player2 = Player.createRedPlayer(name: 'red_nico', age: 14);
  player1.sayHello();
  player2.sayHello();
}

 

 

 

- Cascade Notation

property의 값을 변경하고자 할때 코드를 줄여 사용할 수 있습니다.

아래 player1과 player2의 property 값을 변경하는 코드는 같은 기능을 합니다.

  var player1 = Player.createBluePlayer(name: 'blue_nico', age: 24);
  player1.name = "blue_nico_change";
  player1.age = 25;

// 아래와 같이 생략하여 사용 가능하다.
  var player2 = Player.createRedPlayer(name: 'red_nico', age: 14)
    ..name = "red_nico_change"
    ..age = 15;

 

 

 

- Enums

위에서 직접 'blue', 'red'를 문자열로 입력하여 사용했으나 휴먼에러를 방지하기 위해 Enum을 통해 미리 팀값을 지정해놓고 사용해야 합니다.

enum Team { red, blue }

class Player {
  late String name; // class에서 property를 선언할 때는 타입을 사용해서 선언.
  late int xp;
  late Team team;
  late int age;

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

  // 생성자의 이름은 class의 이름과 같아야 합니다.
  Player({
    required this.name,
    required this.xp,
  });

  Player.createBluePlayer({
    required this.name,
    required this.age,
  })  : this.team = Team.blue,
        this.xp = 0;

  Player.createRedPlayer({
    required this.name,
    required this.age,
  })  : this.team = Team.red,
        this.xp = 0;
}

 

 

추상화, 상속을 받아 클래스를 작성할 수도 있습니다.

class Human {
  final String name;
  Human(this.name);
  void sayHello() {
    print("Hi my name is $name");
  }
}

enum Team { red, blue }

class Player extends Human {
  late String name; // class에서 property를 선언할 때는 타입을 사용해서 선언.
  late int xp;
  late Team team;
  late int age;

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

  @override
  void sayHello() {
    super.sayHello();
    print('!!');
  }
}

void main() {
  Player player = Player(name: "nico", xp: 1500);
  player.sayHello();
}

 

 

 

- mixins

생성자가 없는 클래스를 의미합니다.

클래스에 프로퍼티와 메소드만 존재하며, with className을 통해 mixins 클래스의 프로퍼티와 메소드를 그냥 긁어오는 것입니다.

// 예시
class Strong {
  final double height = 1.99;
}

class Player with Strong {
...
}

 

 

 

다음 포스팅에서는 Flutter 강의에 대해 공부하고 요약하는 글을 가지고 올 예정입니다.

끝.

728x90
반응형
댓글