[ STUDY ]/끄적끄적..

[Flutter] Dart언어

김강니 2023. 3. 20. 17:24

특징


  1. main()함수로 시작
  2. 어디에서나 변수선언, 사용 가능
  3. 모든 변수가 객체, 모든 객체는 object클래스 상속받음
  4. dynamic타입 이용(dynamic : 여러 자료형 허용)
  5. 외부로 노출하고 싶지 않을 경우 변수나 함수 앞에 언더스코어(_) 사용
  6. 제네릭타입을 사용해 개발 가능
  7. null safety wldnjs : 컴파일 전 널 예외(null exeption)을 알 수 있음 -> null에 대한 오류가 발생하지 않도록 작업 가능

 

 

VARIABLES


final : javascript의 const역할
const : compile-time constant(compile-time에 알고 는 값이어야 함) API에서 받아야하는 변수 값은 X
late : final이나 var앞에 붙이는 수식어 : 초기 데이터 없이 변수 선언 가능
 

Null safety 

: 어떤 변수, 혹은 데이터가 null이 될 수 있음을 명시


*기본적으로 모든 변수는 non-nullable

자료형? : null값 가능
List<자료형?> : List에 null값 포함 가능
List<자료형>? : List 자체가 null일 수 있음
! : null이 아님을 직접 표시

void main() {
	String? abc = 'abc';
    abc = null;
    abc?.isNotEmpty;
    //abc가 null이 아니라면 isNotEmpty속성 적용

 

 

DATA TYPES


자료형


구분자료형설명

숫자 int 정수형 숫자
double 실수형 숫자
num 정수형 또는 실수형 숫자
문자열 String 텍스트 기반 문자
불리언 bool True or False
자료형 추론 var 입력받은 값에 따라 자료형 결정, 한 번 결정된 자료형은 변경불가
dynamic var과 같지만 dynamic은 다른 병수 입력하면 자료형 변경 가능

 

Lists


List 생성

void main() {
	var numbers = [1, 2, 3, 4];
    	//List<int> numbers = [1, 2, 3, 4];
}

 
String Interpolation

//변수가 이미 존재할 경우
void main() {
	var name = 'gaeun';
    	var greeting = 'Hello everyone, my name is $name, nice to meet you!';
    	print(greeting); // 실행결과 : Hello everyone, my name is gaeun, nice to meet you!
}

//계산을 거쳐서 결과 값을 구할 경우
void main() {
	var name = 'gaeun';
    	var age = 20;
    	var greeting = 'Hello everyone, my name is $name and I\'m ${age + 2}';
    	print(greeting); // 실행결과 : Hello everyone, my name is gaeun and I'm 22
}

 
Collection if

void main() {
	var giveMeFive = true;
	var numbers = [1, 2, 3, 4, if(fiveMeFive)5];
    	print(numbers); // 실행결과 : [1, 2, 3, 4, 5]
}

 
Collection For

void main() {
	var oldFriends = ['gaeun', 'kihyun'];
    	var newFriends = [
    	'lewis',
    	'ralph',
    	'darren',
    	for (var friend in oldFriends) "❤ $friend"
    	];
    	print(newFriends); // 실행결과 : [lewis, ralph, darren, ❤ gaeun, ❤ kihyun]
}

 

Maps


Map 생성

void main() {
	var player = { //Map<String, Object> player(object는 어떤 자료형도 될 수 있음)
    //Map<자료형, 자료형> player로 쓸 수 있음
    	'name': 'gaeun',//key: value
        'xp': 19.99,
    	'superpower': false,
  };
}

 
복잡한 key설정

//1
void main() {
	Map<List<int>, bool> player = {
    	[1, 2, 3, 5]: true,//key를 List로
  };
}

//2
void main() {
	List<Map<String, Object>> players = [
   	{'name': 'gaeun', 'xp': 19.99},
    	{'name': 'gaeun', 'xp': 19.99},
  	];
}

 

Sets


Set 생성

void main(){
	var numbers = {1, 2, 3, 4};
    //Set<int> numbers = {1, 2, 3, 4};
    //Set은 모든 요소가 Unique
}

 

 

FUNCTIONS


*return = =>

Named Parameters


//Null Safety
//1 : named argument에 default value 정하기
String sayHello({String name = 'gaeun', int age = 20, String country = 'korea'}) {
  	return "Hello $name, you are $age, and you come from $country";
}

//2: 함수의 변수들이 반드시 값을 가져야 된다고 입력함. 함수호출시 오류.
String sayHello({
	required String name = 'gaeun', 
    required int age = 20, 
    required String country = 'korea'}) {
  	return "Hello $name, you are $age, and you come from $country";
}

void main() {
	print(sayHello(
	age: 12,
	country:'korea',
 	name: 'gaeun'
    //순서를 매번 기억할 수 없으니 함수의 매개변수를 중괄호로 묶고 함수의 정의를 보고 값 전달
  ));
}

 

Optional Positional Parameters


String sayHello(
	String name, 
    int age, 
    [String? country = 'korea']//country값이 null이 될 수 있음, default value
    ) => 'Hello $name, you are $age years old from $country';
    
void main() {
	sayHello('gaeun', '20'); // Hello gaeun, you are 20 years old from korea
}

 

Operator


- ?? : QQ Operator

//expr1 ?? expr2 : expr1이 null이 아닌경우 해당 값을 반환, 그렇지 않으면 expr2의 값을 평가
print(0 ?? 1); //0
print(null ?? null); //null
print(null ?? null ?? 2); //2
//1
String capitalizeName(String? name) {
  	if (name != null) {
    	return name.toUpperCase();
  	}
  	return 'ABC';
}
//2 삼항연산자
String capitalizeName(String? name) =>
	name != null ? name.toUpperCase() : 'ABC';
//3 QQ Operation
String capitalizeName(String? name) =>
	name?.toUpperCase() ?? 'ABC';

void main() {
  	capitalizeName('gaeun');
  	capitalizeName(null);
}

- ??= : null-aware assignment

//??= : 변수가 null값인 경우에만 값 대입
int value;
print(value); //null
value ??= 5; //5
value ??= 6; //6

 

- ?. : null-aware access

//피연산자가 null일 수 있음
void main() {
  String? input;
  print(input?.length); // null
  print(input?.toLowerCase()); // null
}

 
- ... : aware spread

//여러개의 항목을 cillection에 간편하게 추가
var list = [1, 2, 3];
var list2 = [0, ...list];  // [0, 1, 2, 3]

 
- ...? : null-aware spread

//추가하려는 항목이 null일 수 있을때 사용
var list;
var list2 = [0, ...?list];

 
cascade

- .. : 한 객체로 해당 객체의 속성이나 멤버 함수를 연속으로 호출가능

var paint = Paint()
  ..color = Colors.black
  ..strokeCap = StrokeCap.round
  ..strokeWidth = 5.0; //세미콜론(;)은 마지막에만
  
//동일한 결과
var paint = Paint();
paint.color = Colors.black;
paint.strokeCap = StrokeCap.round;
paint.strokeWidth = 5.0;

 

Typedef

alias 붙이기


typedef ListOfInts = List<int>;

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

void main(){
  print(reverseListOfNumbers([1, 2, 3]));
  //[3, 2, 1]
}
typedef UserInfo = Map<String, String>;

String sayHi(UserInfo userInfo){
  return "Hi ${userInfo['name']}";
}

void main(){
  sayHi({"name": 'gaeun'});
}

 

 

CLASSES


* Class에서 property를 선언할때는 타입을 사용해서 정의

class 생성하기

class Player{
  String name = 'gaeun';//값을 바꾸찌 못하게 하려면 타입 앞에 final
  int xp = 1500;
  
  void sayHello(){
    print("Hi my name is $name");
  }
}

void main(){
  var player = Player();//new는 생략가능
  print(player.name); //gaeun
  player.name = "gaga";
  print(player.name); //gaga
  player.sayHello(); //Hi my name is gaga
}

 

 

Constructors


class Player{
  late final String name;
  //name이라는 final property에 값이 없어서 에러.
  //late를 써서 변수들의 값을 나중에 받도록 함
  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("gaeun", 1500);
  player.sayHello();//Hi my name is gaeun
  var player2 = Player("gaga", 2500);
  player2.sayHello();//Hi my name is gaga
}

더 간단한 코드

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("gaeun", 1500);
  player.sayHello();//Hi my name is gaeun
  var player2 = Player("gaga", 2500);
  player2.sayHello();//Hi my name is gaga
}

 

Named Constructor Parameters


argument가 여러개일 경우 각자의 위치를 기억해야 한다. 이러한 문제점 해결

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

  Player(
      {required this.name,
      required this.xp,
      required this.team,
      required this.age,});//Named Constructor parameters

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

void main() {
  var player = Player(
    name: "gaeun",//key: value
    xp: 1200,
    team: 'blue',
    age: 21,
  );
  
  var player2 = Player(
    name: "gaga",
    xp: 1500,
    team: 'red',
    age: 24,
  );
}

 

Named Constructors


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

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

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

  Player.createRedPlayer(String name, int age) //positional syntax
      : 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: "gaeun",
    age: 21,
  );
  var redplayer = Player.createRedPlayer("gaeun", 21);
}

 

- API로부터 여러 Player가 들어잇는 목록을 받을 경우

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

  Player.fromJson(Map<String, dynamic> playerJson)
      : name = playerJson['name'],
        xp = playerJson['xp'],
        team = playerJson['team'];

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

void main() {
  var apiData = [
    {
      "name": "gaeun",
      "team": "red",
      "xp": 0,
    },
    {
      "name": "lynn",
      "team": "red",
      "xp": 0,
    },
    {
      "name": "dal",
      "team": "red",
      "xp": 0,
    },
  ]; //구조화되지 않은 세개의 element

  apiData.forEach((playerJson) {//forEach : 자동으로 반복문실행
    var player = Player.fromJson(playerJson);
    player.sayHello();
    //Hi my name is gaeun
	//Hi my name is lynn
	//Hi my name is dal
  });
}

 

cascade Notation


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 ga = Player(name: 'gaeun', xp: 1200, team: 'red');
  var potato = ga
    ..name = 'las'
    ..xp = 12000
    ..team = 'blue'
    ..sayHello(); //Hi my name is las
}

 

Emnums


값을 잘못넣는 실수를 줄일떄 사용

enum Team { red, blue }
enum XPLevel { beginner, medium, pro }

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

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

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

void main() {
  var ga = Player(name: 'gaeun', xp: XPLevel.beginner, team: Team.red);
  var potato = ga
    ..name = 'las'
    ..xp = XPLevel.pro
    ..team = Team.blue
    ..sayHello(); //Hi my name is las
}

 

Abstract Classes(추상화 클래스)


추상화 클래스는 특정 메소드를 구현하도록 강제한다.

abstract class Human {
  void walk();
}
//Human추상화 클래스는 이를 상속받는 모든 클래스가 가지고있어야 하는 메소드를 정의함.

enum Team { red, blue }

enum XPLevel { beginner, medium, pro }

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

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

  void walk() {
    print("im walking");
  }

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

class Coach extends Human {
  void walk() {
    print('the coach is walking');
  }
}
//Player와 Coach클래스가 walk메소드를 가지고 있다는 걸 알 수 있음

void main() {
  var ga = Player(name: 'gaeun', xp: XPLevel.beginner, team: Team.red);
  var potato = ga
    ..name = 'las'
    ..xp = XPLevel.pro
    ..team = Team.blue
    ..sayHello(); //Hi my name is las
}

 

Inheritance(상속)


class Human {
  final String name;
  Human(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 name,
  }) : super(name);
  //main의 palyer에서 name을 받아 Player의 name에 넣고 부모임 Human클래스의 생성자에도 즉시 전달
  //super : 부모 클래스와 상호작용 할 수 있도록 해준다

  @override
  void sayHello() {
    super.sayHello();
    print("and I play for ${team}");
  }
}

void main() {
  var player = Player(team: Team.red, name: 'gaeun');
}

 

Mixins

생성자가 없는 클래스


클래스에 프로퍼티들을 추가할 때 사용함.

class Strong {
  final double strenghtLevel = 1500.99;
}

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

class Tall {
  final double height = 1.99;
}

enum Team { blue, red }

class Player with Strong, QuickRunner, Tall {
  final Team team;

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

class Horse with Strong, QuickRunner {}

class Kid with QuickRunner {}
//with : 단순히 Mixin 내부의 프로퍼티와 메소드들을 가져오는 것, 부모클래스 X

void main() {
  var player = Player(
    team: Team.red,
  );
  player.runQuick();
}