김마드 2023. 7. 8. 17:41

VARIABLES

1. 변수 선언 방법

var name = "jh" 또는

String name = "jh"

으로 선언 할 수 있는데 보통 지역 변수선언할 때 var를 사용한다. 그리고 변수가 선언 되면 같은 해당 변수명의 값을 바꿔줄 수 있는데 이때는 같은 타입의 데이터로만 바꿀 수 있다.

 

var가 아닌 데이터 타입으로 선언할 때는 보통 class에서의 property에 쓰인다. 이건 나중에 강의 더 보면 이해 될 듯 하다.

 

2. dynamic type

다이나믹 타입은 var name; 으로 해버리면 해당 변수의 값의 타입에는 무엇이든 올 수 있다. 보통 잘 안쓰지만 꼭 필요할때가 있다고 한다. 값을 받아올 때 해당 타입이 어떤 것인지 모를 때, if(name is String) { ~~~ } 하는식으로 써먹으면 될 듯하다.

 

3. nullable

기본적으로 변수를 선언할 때 null값은 못받는 걸로 되어 있다.

String name = "jh"

name = null

은 문제가 된다. 하지만 여기서 String? name = "jh"와 같이 ?를 타입 뒤에 붙여주면 null값을 받을 수 도 있다는 뜻이다. api data 를 받아올 때 조건문식으로 쓰면 된다. name?.xxx 하면 name의 값이 null이 아니라면 xxx 한다라는 조건문이다.

 

4. final

final name = "jh" 하면 해당 name 변수는 나중에 값을 바꿀 수 없다. js의 const와 똑같은 기능이라 보면 된다.

 

5. late

api data를 받아오는 data fetching때 매우 유용하다.

late final String name; 으로 먼저 선언 한 후, api 데이터를 받은 후 해당 name값에 받아온 data 값을 할당하는 식으로 하면 될 듯 하다. 

 

6. const

컴파일 할 때 이미 고정된 상수 값이어야 한다. api data 값 같은게 들어가면 안된다. 앱스토어에 올리기 전에 이미 알고 있는 값을 다룰 때 쓰인다.

const api_key = "1232132131" 이런식

(자바스크립트의 const는 dart의 final이랑 비슷하다고 보면 된다.)

 

DATA TYPES

1. list

기본적으로 js의 배열과 같은 기능을 한다. 여기에 collection if 라는 신기능이 있다. 아래와 같이 배열의 마지막에 if 문을 추가해서 값을 넣을 수 있다. 이게 콜렉션 이프.

void main() {
  var giveMeFive = true;
  var numbers = [
    1,
    2,
    3,
    4,
    if (giveMeFive) 5,
  ];
  print(numbers);
}

 

2. String Interpolation

js의 ${변수값} 이랑 똑같은 기능을 한다. 대신에, 대신에 해당 변수값에 변동이 없을시에는 {}를 생략해도 된다.

void main() {
  var name = "jh";
  var old = 30;
  var test = "$name is my name, I am ${old + 2}";
  print(test);
}

 

3. collection for

collection if와 같이 배열 값에 무언가를 추가해줄 수 있는데, 이때 js의 map함수와 같은 기능을 사용 할 수 있다.

void main() {
  var oldFriends = ["jh", "jj"];
  var newFriends = [
    "aa",
    "bb",
    for (var friend in oldFriends) "😀 $friend",
  ];
  print(newFriends);
  // 결과 값 [aa, bb, 😀 jh, 😀 jj]
}

4. map

js의 object와 같은 기능이다.

void main() {
  var player = {"name": "jh", "haha": true};
  print(player);
}

 

5. set

list와 유사하지만, 해당 set값의 각 각의 값은 유니크 하다. 아래 같은 경우는 1,2,3,4의 값이 이미 있기 때문에 해당 set값에 1,2,3,4 어느 값도 더 추가할 수가 없다. (5는 추가 가능)

void main() {
 var numbers = {1,2,3,4}
}

6. optional positional parameters

position parameter에서 null 값이 들어갔을 때 디폴트 값을 지정하는 방법은 아래와 같다. (자주 사용 하지 않는 다고함)

sayHello(String name, int age, [String? country = "vn"]) {
  return "Hello $name nice to meet you! and $age $country";
}

void main() {
  print(sayHello("jh", 30));
}

 

FUNCTIONS

1. defining a funtion

Dart는 진정한 객체 지향 언어이므로 함수도 객체이며 타입이 Function입니다. 이는 함수를 변수에 할당하거나 다른 함수에 인수로 전달할 수 있음을 의미합니다.
```
// 하나의 표현식만 포함하는 함수의 경우 아래와 같이 단축 구문을 사용할 수 있습니다.
String sayHello(String name) => "Hello ${name} nice to meet you.";

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

void main() {
print(sayHello("sugar"));
}
```

 

2. named parameters

Named parameters는 명시적으로 required로 표시되지 않는 한 선택 사항입니다. 기본값을 제공하지 않거나 Named parameters를 필수로 표시하지 않으면 해당 유형은 기본값이 null이 되므로 null을 허용해야 합니다.
```
String sayHello(
{required String name, required int age, required String country}) {
return "${name} / ${age} / ${country}";
}

void main() {
print(sayHello(name: "sugar", age: 10, country: "Korea"));
}
```

 

3. optional positional parameters

Dart에서 [] 은 optional, positional parameter를 명시할 때 사용된다.
name, age는 필수값이고 []를 통해 country를 optional값으로 지정해줄 수 있다.

```
String sayHello(String name, int age, [String? country = ""]) {
return 'Hello ${name}, You are ${age} from the ${country}';
}

void main() {
var result = sayHello("sugar", 10);
print(result);
}
```

 

4. QQ Operator

js의 삼항 연산자 기능과 똑같은 기능이 있다. a? b : c --> a가 true면 b고 false면 c다.

 

?? 연산자를 이용하면 왼쪽 값이 null인지 체크해서 null이 아니면 왼쪽 값을 리턴하고 null이면 오른쪽 값을 리턴한다.

(이것도 js와 동일)
```
String capitalizeName(String? name) {
return name?.toUpperCase() ?? "";
}
```

??= 연산자를 이용하면 변수 안에 값이 null일 때를 체크해서 값을 할당해줄 수 있다.
```
void main() {
String? name;
name ??= "sugar";
name = null;
name ??= "js";
print(name); // js
}
```

5. typedef

자료형에 사용자가 원하는 alias를 붙일 수 있게 해준다. (자료형 이름의 별명을 만들 때 사용)
```
typedef ListOfInts = List<int>;

ListOfInts reverseListOfNumbers(ListOfInts list) {
var reversedList = list.reversed.toList();
return reversedList;
}
```

 

CLASSES

1. class 기본

class 에서 property에서는 반드시 변수명 앞에 type을 명시해주어야 한다. (함수 내에서는 var써도됨)

그리고 class내 method에서 property를 호출 할때는 this.name과 같이 this를 안써줘도 된다. 

class Player {
  String name = "jh";
  int xp = 2000;
  void sayHello() {
    print("hi my name is $name");
  }
}

void main() {
  var player = Player();
  player.sayHello();
}

 

2. constructors

아래와 같이 생성자를 만들어줘도 되는데, 너무 번거롭고 길어지기 때문에 그 다음 코드대로 요약해서 진행한다.

(생성자명은 class명과 동일하게 해야함)

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("jh", 1500);
  player.sayHello();
  var player2 = Player("haha", 2500);
  player2.sayHello();
}
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("jh", 1500);
  player.sayHello();
  var player2 = Player("haha", 2500);
  player2.sayHello();
}

 

3. named constructor parameters

함수 named와 같이 class에서도 똑같이 사용 할 수 있다. 아래 코드 참조. (named로 습관 길들이는게 좋을듯 - 코드 깨끗)

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

void main() {
  var player = Player(
    name: "jh",
    xp: 1500,
    team: "red",
    age: 30,
  );
  player.sayHello();
}

 

4. named constructors

만약 생성자(constructor) 함수를 여러개 만들고 싶다면 어떨까?

Player.createBluePlayer({
required String name,
required int age,
}) : this.age = age,
this.name = name,
this.team = 'blue',
this.xp = 0;
```
콜론(:)을 사용하면 특별한 생성자 함수를 만들 수 있다.
콜론을 넣음으로써 dart에게 여기서 객체를 초기화하라고 명령할 수 있다.

 

✅ Named parameters
// 일반적인 방법
Player.createBlue({
required String name,
required int xp
}) : this.name = name,
this.xp = xp,
this.team = 'blue';

// 간소화된 방법(dart는 간소화된 방법을 추천)
Player.createRed({
required this.name,
required this.xp,
this.team = 'red',
});

✅ positional parameters
// 일반적인 방법
Player.createRed(String name, int xp)
: this.name = name,
this.xp = xp,
this.team = 'red';

// 간소화된 방법
Player.createRed(
this.name,
this.xp,
[this.team = 'red']
);

 

5. cascade notation

앞에서 선언한 class를 동일하게 사용할 경우 아래와 같이 ; 를 없애고 .. .. 으로 연속해서 쓸 수 있다. (마지막에 ; 써야함)
이때 ..는 앞에서 선언한 class 변수명을 뜻한다. 

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 $team");
  }
}

void main() {
 
  var player = Player(name: "jh", xp: 10, team: "red");
    player.name = "haha";
    player.team = "haha team";
// 대신, 아래 처럼 요약해서 사용
 
  var player = Player(name: "jh", xp: 10, team: "red")
    ..name = "haha"
    ..team = "hahateam";
  player.sayHello();
}

6. enums

enum은 우리가 실수하지 않도록 도와주는 타입이다.
dart에서 enum type을 만드는 법은 다음과 같다
```dart
enum Team {
red,
blue,
}
class Player {
String name;
int age;
Team team;

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

void main(){
var jisoung = Player(name: "jisoung", age: 17, team: Team.red);
var sushi = jisoung
..name = "sushi"
..age = 12
..team = Team.blue;
```

 

7. abstract (추상) class

Human을 abstract로 추상화 class로 선언해놓고 다른 class에서 해당 Human class로 extend 할 수 있다. 이때 반드시 abstract되었던 메소드를 써야한다. 안쓰면 에러남.

abstract class Human {
  void walk();
}

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

  void walk() {
    print("I am walking");
  }

 

8. inheritance(상속)

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

enum Team { blue, red }

class Player extends Human {
  final Team team;

  Player({
    required this.team,
    required String playerName,
  }) : super(name: playerName);
 
//아래와 같이 써도됨
  Player({required this.team, required super.name});

//아래는 override를 통해 상속받은 메소드를 대체 할 수 있음.
  @override
  void sayHello() {
    super.sayHello();
    print("and I play for $team");
  }
 
}

void main() {
  var player = Player(team: Team.red, playerName: "jh");
  player.sayHello();
}

9. mixin

여러 class에서 쓰일 속성이나 메소드를 mixin을 통해서 미리 정의해놓을 수 있다. mixin에는 생성자가 있어서는 안된다.

아래와 같이 사용 가능.

mixin Strong {
  double power = 100.4;
}

mixin Faster {
  void runQuick() {
    print("I'm so fast");
  }
}

mixin Tall {
  final double height = 1.99;
}

class Player with Strong, Faster, Tall {}

class children with Faster {}

class horse with Strong, Faster {}

void main() {
  var player = Player();
  print(player.power);
}