[Flutter] 2 플러터 시작 ( Dart 문법 )

김호정's avatar
Sep 26, 2024
[Flutter] 2 플러터 시작 ( Dart 문법 )
 

1. 개념 설명

 
Dart 언어
 
타입스크립트 가 같이 튀어나옴
 
→ JavaScript에 타입을 넣은 업그레이드 버전
 
그래서 타입스크립트가 인기가 많았다.
 
NodeJS → JVM 같은거
 
자바스크립트는 브라우저 없이 실행할 수 있다.
 
 
구글에서 퓨시아라는 OS를 만들고 있었는데
 
인터페이스가 마우스, 키보드가 아니라
 
음성인식으로 동작.
 
 
 
초경량 OS임 용량도 작고.
 
OS를 다 개발하고 나서
 
만들어지는 앱의 그림을 어떻게 그리지 ? 하는 의문이 생김.
 
notion image
플랫폼 - OS 랑 하드웨어
 
 
퓨시아는 shell (명렁어) 대신 Dart를 쓴다
 
→ Dart 로 UI 라이브러리를 만드는 것 이다.
이 UI 라이브러리를 Flutter 라고 한다.
 
“플러터 UI 프레임워크”
 
스키아 → 그림 그리는 엔진
 
 
스키아 엔진을 사용해서 Dart 로 그림 그린거 그대로 휴대폰에 갈아끼운다.
 
 
AOT (Ahead of Time) : 실행되기 전에 목적 코드로 바뀌었다. !
 
플러터 - 스키아 엔진 을 통해서 나온 그림을 HW에 바로 ㄱㄱ
 
개발모드에서는 JIT 을 던짐
 
JIT (Just In Time)
 
어헤드오브타입은 전체 코드를 뒤집어 엎는다. ( 펌웨어 )
 
JIT는 변경된 부분만 찾아서 컴파일해서 OS에 던진다.
 
 
 
자바는 하이브리드 언어여서 AOT + JIT 임
 
C언어는 다 AOT
 
자바스크립트는 JIT로 실행 → 애는 프로덕션 모드에서도 JIT로 실행
 
notion image
notion image
 
 
 
 

2. DartPad


 
 
notion image
 
여기서 다트 언어 연습할 수 있다.
 

3. 연습

 
notion image
 
만들고 VSCode로 열기
 
notion image
 
터미널에서 dart —version 해보면 환경변수에 어제 설정해놨기 때문에 잘 뜬다.
 
 
 
VSCode 로 개발하자
 
그러기 위해서는 플러그인 설치
 
notion image
 
Dart 랑 Dart syntax highlighting 설치
 
 
notion image
 
name , main은 static 에 뜬다.
 
처음부터 static에 떠버린다.
 
클래스 안에 있는게 아닌건 처음부터 뜬다.
 
static 에 뜨니까 static이라고 붙일 필요 없다.
 
class Animal{
int id = 1;
static String name = “동물”;
}
 
String name = “Hello world”;
 
클래스 정적 메모리에 할당 → Animal 안에 있는거
전역 정적 메모리에 할당 → 밖에 있는 거
 
바깥에 적혀있는 애들은
1급 객체여서 정적 메모리에 뜬다.
 
 
나중에 ex01을 다른데서 import 하면 바로 name 을 사용할 수 있다.
 
 
notion image
 
run 하면 프린트 된다.
 
 
notion image
 
메서드는 클래스 내부에 있어야 한다.
 
나중에 위젯 만들때 extract ? 해서 메서드로 코드 뺄때도
클래스안으로 빼야한다.
 
notion image
 
13번 라인에서 Animal이 new 되었으니까 int id 가 뜬다.
 
어디 ? heap 에 뜬다.
 
메모리 어디에 뜨는지 아는게 중요하다!
 
 
notion image
 
hello는 상태가 없다.
 
→ 메서드가 아니라 함수다. (기능을 가지는 친구)
 
speak는 상태(id, name)를 확인하거나 바꾸는 애다.
 
→ 메서드
 
 
 
 
notion image
 
int num = 10; 은 stack에 뜬다.
 
notion image
 
int id 는 Animal 이 new 될때 heap에 뜨고.
함수, 메서드 안에 있는건 stack 에 뜨는건가 ?
 
 
 
 
notion image
 
 
 
int 4 바이트 할당
double 8 바이트 할당
bool 1개는 1bit인데 메모리의 크기가 1byte이기 때문에 1byte를 차지.
String 은 커서 할당을 못함
 
 
 
모두 1급 객체이다.
n1, d1, b1, s1 각각 다 “객체”라고 !!!
 
++
인터프리터 → 타입이 들어갈 때 결정된다.
 
 
notion image
 
var은 “선언”만 한 것.
 
stack 열릴때 var은 메모리에 안잡힌다.
 
실행해봐야 안다. → “타입추론”
 
💡
var초기값에 따라 타입이 결정되며, 이후 그 타입을 고정적으로 사용해야 한다
 
notion image
 
var n1 = 1 은 int 타입으로 타입추론이 되었기 때문에 ?
타입변경이 불가능 하다! 그래서 스트링을 넣으려고 하니까 에러남
 
 
 
notion image
notion image
 
dynamic 은 모든 타입을 다 받을 수 있는 Object 타입!!!!
 
중간에 다른 타입으로 변경 가능하다.
 
 
notion image
var 이면 n1이 int 로 결정나고 나서 n1에 문자열이나 double를 넣으려고 하면 에러 난다.
 
notion image
dynamic이면 타입을 바꿀 수 있다 : )
 
notion image
// 나머지 print("3%2=${3%2}"); // 몫 구하기 print("3~/2=${3~/2}");
% 는 나머지
~/는 몫을 구할 수 있다.
 
 

 

NULL 대체 연산자

삼항 연산자보다 좋다.
 
notion image
 
String username = null;
 
이렇게 null을 받을 수는 없다.
 
notion image
 
String? username = null;
 
이렇게 새로운 String? 타입으로 받는다.
 
? 이렇게 물음표를 같이 써줘야 한다.
 
notion image
 
Class A {
int? num;
 
A(){}
}
 
기본생성자를 때릴때 null 이 들어올 수 있으니
int? 이렇게 처리 해줘야지 에러가 안난다.
 
( 아님 나중에 들어온다고 int 앞에 late 붙여줘도 에러 안나는듯? )
 
notion image
 
late를 붙이면 나중에 무조건 들어옴
(아빠가 원래부자면 나중에 무조건 차 사줄거니까)
 
notion image
 
?는 null 일 수 있음
(일단 이 자식이 태어날때부터 car는 없지만
나중에 car를 아빠가 사줄수 있으니까)
 
 
처음부터 초기화가 이루어 져야 하는 것은 ? 붙일 필요가 없다.
 
class Student {
String name; // 이름은 처음부터 학생이 들고 있는 거니까 ?를 붙일 필요가 없다.
// null 이 들어오지 않으니까
 
}
 
 
notion image
 
null을 받을때는 ? 붙인다.
 
 
null 대체 연산자
null 대체 연산자
 
username이 null 이면 “임시아이디”를 return 함
 
삼항 연산자와 null 대체 연산자는 익스프레션(표현식) → 값을 반환
 
if는 표현식이 아니라 그냥 실행문이다.
→ 실행문은 특정 동작을 수행하기 위한 코드 블록을 나타내며, 실행문은 값을 반환하지 않습니다. 대신 코드가 실행되고 그에 따른 부작용(출력, 변수 변경 등)이 발생합니다.

표현식과 실행문

💡
코드와 필기 내용을 분석하면, 필기에서 설명하는 부분은 삼항 연산자(?:), null 대체 연산자(??), 그리고 if 문 간의 차이를 설명하고 있는 것입니다. 여기서 중요한 개념은 **"표현식(expression)"**과 **"실행문(statement)"**의 차이입니다.

1. 삼항 연산자와 null 대체 연산자

삼항 연산자와 null 대체 연산자는 **표현식(expression)**입니다. 표현식은 값을 반환하는 코드입니다. 즉, 코드가 어떤 값을 평가하고, 그 결과값을 반환합니다. 표현식을 다른 코드에 끼워 넣을 수 있고, 그 자체가 값이 됩니다.
  • *삼항 연산자 (?:)**는 조건에 따라 두 가지 값을 반환합니다.
    • dart 코드 복사 print(username == null ? "임시아이디" : username);
      이 코드에서 username == null 조건이 참일 때 "임시아이디"를 반환하고, 거짓일 때 username 값을 반환합니다. 삼항 연산자는 항상 값을 반환하므로 그 자체가 표현식입니다.
  • *null 대체 연산자 (??)**도 값을 반환하는 표현식입니다.
    • dart 코드 복사 print(username ?? "임시아이디");
      이 코드에서는 username이 null일 경우 "임시아이디"를 반환하고, null이 아닐 경우 username을 반환합니다. 역시 표현식이므로 값을 반환하고, 다른 코드에서 사용할 수 있습니다.

2. if 문과 표현식의 차이

필기에서 언급된 것처럼, if 문은 **실행문(statement)**입니다. 실행문은 특정 동작을 수행하기 위한 코드 블록을 나타내며, 실행문은 값을 반환하지 않습니다. 대신 코드가 실행되고 그에 따른 부작용(출력, 변수 변경 등)이 발생합니다.
예를 들어:
dart 코드 복사 if (username == null) { print("임시아이디"); } else { print(username); }
if 문은 조건에 따라 실행할 코드 블록을 선택합니다. 하지만 값을 반환하지는 않습니다. 즉, 이 자체는 표현식이 아니고, 다른 코드 안에 넣어서 사용할 수 없습니다. 이 코드가 실행되면 그저 출력문이 실행될 뿐, 결과값을 반환하지 않습니다.

정리

  • 표현식(expression): 값을 반환하는 코드. 삼항 연산자(?:)와 null 대체 연산자(??)는 표현식으로, 값을 반환하여 다른 코드에 사용할 수 있습니다.
  • 실행문(statement): 실행만 하고, 값을 반환하지 않는 코드. if 문은 조건에 따라 특정 코드를 실행할 뿐, 값을 반환하지 않으므로 표현식이 아닙니다.
그래서 필기에 적힌 내용은 삼항 연산자와 null 대체 연산자가 "표현식"이라서 다른 코드에서 값으로 사용할 수 있다는 뜻이고, if 문은 "실행문"이라 값을 반환하지 않고 단순히 특정 코드를 실행하는 문이라는 차이를 설명한 것입니다.
 
 
 
notion image
 
add 함수 출력.
 
notion image
notion image
 
Dart 는 오버로딩을 지원하지 않는다.!!!
 
notion image
 
타입을 안적으면 타입추론을 한다.
→ 타입을 안적으면 var
→ 매개변수에 타입추론이 가능. 타입 적어도 되고 생략도 가능하다.
 
notion image
 
이렇게 타입을 넣어서 적을 수도 있다.
 
notion image
 
근데 타입을 안 적어놨는데 이렇게 스트링이 들어가면 안되는걸
몰라서 다른 개발자가 스트링을 넣어서 돌리면 터질 수 있다.
 
++
그래서 다같이 협업할때는 타입이 필요하다.
큰 회사에서 수백명이 협업할때 타입이 필요해서
타입스크립트를 많이 쓴다.
 
자바스크립트는 타입이 없어서 협업 힘드러.
 
notion image
 
타입을 적어주니 문자열을 넣으면 IDE가 빨간줄로 안되는걸 알려준다.
→ 이렇게 타입을 적어주면 에러 나기 전에 안된다는걸 미리 알 수 있다.
 
(집에서 복습중인데 내 VSCode 는 안알려주는데 ?ㅠㅠ)
 
 
notion image
notion image
 
var 타입은 return이 안된다.
 
notion image
 
dynamic은 return 할 수 있다.
 
notion image
 
프린트 안에 넣을 수 있으면 익스프레션이다 (표현식=return 하는애)
 
notion image
 
return 하지 않는 add 함수를 넣어서 print 하려고 하니 안된다.
 
notion image
 
Function은 함수를 저장하는 타입
 
변수(f)에다가 함수(multi)를 대입해서 넣음 (가능) →
함수는 1급 객체이니까
 
notion image
 
근데 익명 함수로 적어야 한다. cant be named !
 
notion image
 
변수에 함수를 넣을때는 익명함수로 적어야 한다.
(){}
int multi 어쩌고 이름 지워줘라.
 
그래야 에러빨간줄 안뜸
 
notion image
 
f 와 minus 함수는 return을 하니까 표현식이라
print안에 적을 수 있다.
return을 안하는 add 함수는 print 안에 적을 수 없다.
 
notion image
 
print 잘 되는 걸 확인할 수 있다.
 
이제 람다식을 적어보자
 
한줄로 표현하고 싶을때는 중괄호랑 return 지워라!
 
notion image
 
이게 람다표현식
 
→ 애는 무조건 리턴을 한다.
 
notion image
 
f2 프린트 하니까 잘된다.
 
notion image
 
한줄로 표현할 수 있을때는 f 처럼 쓰지말고 f2 함수처럼 람다표현식을 쓰고 n1=3처럼 코드가 더 들어가야 해서 한줄로 못쓰면 위의 f1 함수처럼 익명함수를 쓰자!
 
 
notion image
 
엄마가 오면 컴퓨터를 끄거나 갑자기 설거지를 할 수 있다.
어떤 행위를 할지는 모른다.
행위를 결정하지 못해서 함수의 행위를 whenComeMother 함수 안에 미리 만들 수 없다.
그래서 애초에 매개변수로 “행위”를 받는다! ( Function beh )
→ 함수는 😀1급객체😀니까!!!! Dart 는 매개변수로 함수 넣을 수 있따!!!!.
 
리스너를 달아서 엄마가 오는지를 보고 있음
 
void whenComeMother(Funtcion beh){
beh();
}
 
이렇게 행위를 실행시키는 코드까지는 짜줌
 
근데 어떤 행위를 해야할지는 쓰는사람(쓰는개발자)이 넣어준다.
 
 
행위를 미리 특정할 수는 없지만
 
함수는 😀1급객체😀니까!!!! Dart 는 매개변수로 함수 넣을 수 있따!!!!.
 
자바는 매서드를 못 넣으니까 인터페이스를 쓰는거고!
( 저번에 인터페이스 자리에 람다식 썼던 거 같은데 ?? )
(자바는 클래스는 매개변수로 넘길수 있지만 1급객체가 아닌 메서드는 매개변수로 못넘기쟈나)
( → 자바 클래스 = 1급객체, 자바 메서드 ≠ 1급객체 )
 
notion image
 
“컴퓨터 끄기”는 재사용안하고 1번만 쓸거다.
 
근데 off 함수 만들어 두면 좀 비효율적.
 
함수 만들어놓고 재사용안할거면… 이때만 사용할거면…
 
위처럼 쓰지 말자!
 
익명함수로 쓰자!
 
 
notion image
 
이렇게 익명함수로 쓰면 재사용 안 할 함수를 따로 안 만들어도 된다. : ) (깔끔)
 
notion image
 
출력되긴 하는데
 
이렇게 return 하지마라
 
( 재사용이 어려워서 그르나 ? )
 
notion image
 
함수를 쓸때는 n1 * n2 의 결과값이 들어가는게 아니라
“식” 그 자체가 들어간다.
 
 
notion image
 
off 함수를 재사용할게 아니면
 
이렇게 쓰지 말거라
 
notion image
 
지피티도 비효율적이라고 한다.
 
 
notion image
 
익명함수를 쓸때는 이렇게 사용하기 ! 1번만 사용할 경우 !
 
 
 
지금까지 코드 ( ex01.dart ~ ex06.dart)
 

ex01

// static > heap > stack class Animal { int id = 1; // heap static String name = "동물"; void speak() { // 메서드 (상태 변경할 때 사용) int nnn = 10; // stack 에 뜬다. } } String name = "Hello World"; void hello() { // 매서드가 아니라 함수다 ( 기능을 가지는 친구 ) int num = 10; // stack 에 뜬다. } void main() { // main 함수!이다. 매서드는 클래스 내부에 있어야 매서드다. print(name); print(Animal.name); Animal a = Animal(); // int id 는 이 라인에서 뜸 print(a.id); }
 

ex02

void main() { int n1 = 1; double d1 = 10.1; bool b1 = true; String s1 = "홍길동"; // print() 함수는 Console에 출력을 해주는 함수입니다. // ${} 를 활용하면 문자열에 변수를 바인딩할 수 있습니다. print("정수 : ${n1}"); print("실수 : ${d1}"); print("부울 : ${b1}"); print("문자열 : ${s1}"); }
 

ex03

void main() { var n1 = 1; n1 = 2; var d1 = 10.1; var b1 = true; var s1 = "홍길동"; print("정수 : ${n1.runtimeType}"); print("실수 : ${d1.runtimeType}"); print("부울 : ${b1.runtimeType}"); print("문자열 : ${s1.runtimeType}"); }
 

ex04

String? username = null; // 전역 정적 메모리 (static) void main() { print(username); print(username == null ? "임시아이디" : username); // 삼항보다 더 깔끔한게 // null 대체 연산자 print(username ?? "임시아이디"); }
 

ex05

// 오버로딩 지원안함 // 타입생략 가능 -> 타입추론 void add(n1, n2) { // 타입을 안적으면 var print(n1 + n2); } int minus(n1, n2) { return n1 - n2; } Function f = (n1, n2) { // 익명함수 n1 = 3; return n1 * n2; }; // 람다 표현식 Function f2 = (n1, n2) => n1 * n2; void main() { int result = minus(1, 2); print(result); print(f(1, 2)); print(f2(1, 2)); }
 

ex06

void whenComeMother(Function beh) { beh(); } void main() { whenComeMother(() => print("컴퓨터끄기")); }
 
 
 
3강 56페이지 부터 보기 !!!!
 
 
자바는 생성자 때릴때 무조건 앞에 new 해야하는데
 
Dart는 new 키워드를 생략할 수 있다.
 
( 59 ~ 60 페이지 보기 )
 
 
 
class Dog { String name; int age; String color; int thirsty; Dog(String name, int age, String color, int thirsty) : this.name = name, this.age = age, this.color = color, this.thirsty = thirsty; } void main() {}
 
생성자의 역할은 초기화!
 
이미 연산된 값을 결과를 집어던져야지
 
생성자 안에서 연산을 하지 마라
 
그래서 Dart 는
 
생성자 안에서 연산을 못하도록 해두었다.
 
그래서 중괄호가 없다. 클린 아키텍쳐 !
(중괄호 대신에 : 이 온다. 그리고 바로 this. 이 온다)
 
Dart 문법에서 연산을 못하도록 강제해 둔다.
 
(넘어온 name, age 등을 바로 필드에 넣음)
 
Dog(String name, int age, String color, int thirsty){
if(age > 30){
this.age = 어쩌고저쩌고;
}
}
 
이렇게 생성자 안에서 연산 불가!
if 사용불가 !
 
class Dog { String name; int age; String color; int thirsty; Dog(String name, int age, String color, int thirsty) : this.name = name == "홍길동" ?"이름없음" : "name", this.age = age, this.color = color, this.thirsty = thirsty; } void main() {}
 
this.name = name == "홍길동" ?"이름없음" : "name",
( name 이 홍길동이면 이름없음 return 하고 아니면 name을 리턴)
생성자안에서 삼항연산자와 람다식은 사용가능 !! (표현식)
 
notion image
삼항연산자 된다.
 
 
 

생성자 Case 1

class Cat { String name; int age; String color; int thirsty; Cat(this.name, this.age, this.color, this.thirsty); // 보통 생성자를 이렇게 사용한다. }
 
Cat(this.name, this.age, this.color, this.thirsty);
보통 생성자를 이렇게 사용한다.
 
받을 때 그대로 받기만 하면 이렇게 생성자를 쓰면 된다.
 

생성자 Case 2

class Dog { String name; int age; String color; int thirsty; Dog(String name, int age, String color, int? thirsty) : this.name = name == "홍길동" ? "이름없음" : "name", this.age = age, this.color = color, this.thirsty = thirsty ?? 0; // thirsty 가 null 이면 0 을 넣어줌 }
 
데이터 받아서 파싱할 때 는 이걸 사용한다.
( → 매개변수로 받아주고 중괄호없이 : 하고 바로
this. )
 
notion image
 
this.name = name == "홍길동" ? "이름없음" : "name",
this.thirsty = thirsty ?? 0; // thirsty 가 null 이면 0 을 넣어줌
 
이렇게 한줄짜리 연산? 비스무리한게 필요할 때는 case2 와 같은 생성자를 사용한다!!!!
 
 
중괄호 사용하는 생성자 문법 쓰지 말고
Case 1, Case 2 를 사용하자 !!!
 

ex 07

class Cat { String name; int age; String color; int thirsty; Cat(this.name, this.age, this.color, this.thirsty); // 보통 생성자를 이렇게 사용한다. } class Dog { String name; int age; String color; int thirsty; Dog(String name, int age, String color, int thirsty) : this.name = name == "홍길동" ? "이름없음" : "name", this.age = age, this.color = color, this.thirsty = thirsty ?? 0; // thirsty 가 null 이면 0 을 넣어줌 } void main() { Dog("홍길동", 1, "", 1); }
 
 

선택적 매개변수

 
 
선택적 매개변수를 배우자.
 
선택적 매개변수는 값을 초기화 할 수 있다.
 
무조건 받으려면 required 를 쓰면 된다.
 
 
notion image
 
{} 중괄호 붙이는거 → 선택적 매개변수
 
넣어도 되고 안넣어도 된다.
 
notion image
 
age와 name을 선택적 매개변수로 넣어놔서 Dog 를 new 했는데 매개변수를 안넣어도 에러가 안난다.
 
notion image
 
이렇게 넣을 수도 있고
 
notion image
 
이렇게 name 만 넣을 수도 있다.
 
그럼 age 는 null이 들어간다.
 
{}
선택적 매개변수는 오버로딩 같은거 !!!
넣어도 되고, 안넣어도 된다.
 
그리고 순서를 선택해서 넣을 수 있기 때문에
 
notion image
notion image
 
이렇게 순서랑 상관없이 넣을 수 있다.
 
→ 선택적 매개변수가 있기 때문에 자바의 builder 패턴을 구현할 필요가 없다!!
 
builder가 넣고 싶은 것만 넣고, 순서도 상관 없었는데 그 빌더패턴의 장점을 선택적 매개변수로 취할 수 있다.
 
 
notion image
 
에러나는건 null 받는 경우를 ? 로 처리하면 사라진다.
 
 
 
값을 무조건 받을거라서 ?를 쓰기 싫으면
생성자에 required 를 써준다.
(Null 들어올 일 없고 무조건 값을 받을 때)
 
⇒ 값을 무조건 받을거면 required
 
notion image
 
required 를 사용하면 선택적 매개변수의 안받아도 되는 기능이 사라진다.
 
무조건 받아야 한다.
notion image
age 가 required인데 name만 넣어주니까 에러남
 
notion image
name은 required가 아니기때문에 안넣어줘도 됨
 
notion image
 
 
둘다 required 붙이면 name과 age를 둘 다 넣어야 한다.
 
class Dog { int age; String name; Dog({required this.age, required this.name}); } // 1. ? 타입이 있고 // 2. {} 선택적으로 받을 수 있다. ( 선택적 매개변수 ) class Cat { int? age; String? name; Cat({this.age, this.name}); } void main() { Dog(name: "토토", age: 10); Cat(age: 10); }
 
 
선택적 매개변수일때는 무조건 받아야 하니까 안되고
? 타입으로 받으면 생성자 받을 때 default 값을 이렇게 설정할 수 있다.
 
class Cat { int? age; String? name; Cat({this.age, this.name = "토토"}); }
 
notion image
notion image
toString을 만들어 age와 name을 콘솔에 찍어보았다.
 

ex 08

class Dog { int age; String name; Dog({required this.age, required this.name}); } // 1. ? 타입이 있고 // 2. {} 선택적으로 받을 수 있다. ( 선택적 매개변수 ) class Cat { int? age; String? name; Cat({this.age, this.name = "토토"}); void cry() { print("야옹"); } String toString() { return "age : ${age}, name : ${name}"; } } void main() { Dog d = Dog(name: "토토", age: 10); Cat c = Cat(age: 10)..cry(); print(d); print(c); }
 

Cascade 연산자 (61쪽)

 
casecade 연산자 = .. 연산자
 
notion image
 
init 매서드 같은건데
 
cascade 를 사용해서
 
한줄로 초기화 하면서 함수를 바로 실행할 수 있다.
 
 
notion image
 
cascade !!!!!
 
class Dog { int age; String name; Dog({required this.age, required this.name}); } // 1. ? 타입이 있고 // 2. {} 선택적으로 받을 수 있다. ( 선택적 매개변수 ) class Cat { int? age; String? name; Cat({this.age, this.name = "토토"}); void cry() { print("야옹"); } String toString() { return "age : ${age}, name : ${name}"; } } void main() { Dog d = Dog(name: "토토", age: 10); Cat c = Cat(age: 10)..cry(); print(d); print(c); }
 

null 처리방법

 
notion image
 
notion image
 
null 이 return 되는걸 처리 못해서 에러나는 것
 
notion image
 
? 붙여주기
 
notion image
 
! 는 무조건 있을 때 붙여줌
→ 반드시 맞을 때는 괜찮은데 위험한 처리
 
id 값으로 5를 넣었으니까 null 이 return 될건데
null 아니고 값 리턴될거라고 ! 를 붙여준 상황 ㅠㅠ
 
notion image
run 하면 이렇게 터진다.
 
notion image
 
1 일땐 괜찮은데
 
 
notion image
 
5 가 들어가서 null 이기 때문에 터진다.
 
그래서 ! 는 사용하면 위험하다.
 
위험한 코드
 
notion image
 
?? 를 사용하면 null일때 다른 값을 넣어줄 수 있다. (null 대체 연산자)
 
orElse 랑 비슷한거.
 
→ 1을 넣으면 1이 return 되고 그 외의 숫자를 넣으면 null 이 return 되니까 0 이 출력됨
 
notion image
 
결과를 double 로 바꾸려고 했는데 null이 return 되어서 터진다.
 
notion image
!는 100%가 아니면 쓰면 안된다.
 
 
이거보다 안전한게 ? 를 쓰는 것
 
 
notion image
 
? 를 적어주면
→ null이 아니면 실행하고 null 이면 실행하지 마라!
 
5 를 넣으면 → null 이 return 되니까 toDouble 을 실행시키지 않고 null 이 된다.
1 을 넣으면 → 1이 return 되니까 toDouble 이 실행되어서 1.0 이 된다.
 
notion image
 
notion image
 
? 붙여줘야 함! null 처리
 
notion image
 
 
위의 3가지는 알아야 한다.
 
 
notion image
 
 
null 이 나오기 때문에 null 대체 연산자 ?? 를 적어줘야 한다.
 
notion image
 
0.0 으로 대체
 
notion image
 
이렇게 한 줄로 적을 수 있다.
 
notion image
 
실행하면 null 이 들어가기 때문에 설정해준 0.0 이 return 된다.
 
 
한줄로 적을 수 있다.
 
자바는
 
int r4 = findById(5);
double r5;
if(r4 == null){
r5 = 0.0;
}else{
r5 = r4.toDouble();
}
print r5;
 
이렇게 써야하는데
 
Dart는
 
double? r3 = findById(5)?.toDouble() ?? 0.0;
 
이렇게 한줄로 사용할 수 있다.
 

ex09

// null 처리방법 int? findById(int id) { return id == 1 ? 1 : null; } void main() { // 1 .get 같은거 int r1 = findById(1)!; print(r1); // 2 null 대체 연산자 - orElse int r2 = findById(5) ?? 0; print(r2); // 3 double? r3 = findById(5)?.toDouble() ?? 0.0; // null일 경우 0 으로 print(r3); }
Share article

keepgoing