Dart

김지원·2023년 9월 26일
0

플러터

ui 그리는 프레임워크
기반 언어 : Dart

만들어져 있는 위젯을 가져다 쓰면 된다

플러터는 모든 곳에서 동작함
플러터는 네이티브언어를 안거치고 다트에서 바로 기계어로 바뀜

기계장치에 코드 넣는거 : 펌웨어


dart

단독적으로 메모리에 올라갈 수 있음 : 1급 객체
함수가 1급객체임

메서드 : 클래스에 속해서 클래스의 상태를 변경시키기 위한 행위


모든 변수는 객체(object)이며 Object 클래스를 상속한다.
다트의 타입은 자바와 달리 원시(primitive) 타입이 없고 모두 참조(reference) 타입이다.


Object : 모든 데이터 타입의 슈퍼타입 (런타임때도 Object타입이라서 사용할때 타입캐스팅 필요)
var : 초기화 하고 나면 타입 변경이 불가능한 미지정 타입
dynamic : 초기화 이후로도 타입 변경 가능한 미지정 타입

num : int형과 double형의 슈퍼타입


타입 추론

Dart 언어는 타입 추론을 지원합니다. 값이 들어올 때 타입을 추론하여 변수를 초기화

void main(){
 var n1 = 1;
 var d1 = 10.1;
 var b1 = true;
 var s1 = "홍길동";

 print("정수 : ${n1.runtimeType}"); // 정수 : int
 print("실수 : ${d1.runtimeType}"); // 실수 : double
 print("부울 : ${b1.runtimeType}"); // 부울 : bool
 print("문자열 : ${s1.runtimeType}"); // 문자열 : String
}

디버그 출력

print("내용");
자바처럼 +변수+ 로 안하고 ${변수}


변수에 null값 허용

타입 뒤에 ?가 붙어야 null이 가능하다

String s = null; // 오류
String? s = null;

null 대체 연산자

print(username ?? "홍길동");
변수의 값이 null이면 홍길동 출력

String? name;
// String name2; // 할당이 안됐을때 null이니까 ? 없으면 못함

void main() {
  print(name); // null 출력
//   print(name.length); // String? 자체가 null이 가능하니까 문법적으로 못함 
  print(name?.length); // 변수에 ? : null 아닐때만 실행
  print(name??"대체".length); // 변수에 ?? : null이면 뒤에 꺼로 대체함
  print(name!.length); // 변수에 ! : null이 아니라고 보증 (근데 null이면 터지니까 위험)
}

삼항 연산자

조건식 ? 참이면 실행 : 거짓이면 실행
point>=60 ? "합격" : "불합격"


선택적 매개변수

class Person {
 String? name;
 int? money;
 // 안받으면 null이니까 ?붙혀야 함

 Person({this.name, this.money}){}
 // {}안에 적으면 선택적 매개변수
 // 안넣었을때 기본값 설정 가능(this.money = 0)
 
 // {} 바깥쪽에 적으면 그냥 매개변수처럼 무조건 받아야 함
 // required 붙히면 선택적 매개변수라도 무조건 받아야 함

 // 사용할때 ctrl+space로 매개변수 선택해서 입력하기

}

cascade

Chef c1 = Chef("홍길동")..cook();
객체를 생성하면서 메서드도 실행하기


이니셜라이저

자식 생성자의 내부 스택이 실행되기 전에 먼저 실행됨

생성자 : 먼저실행됨 {여기보다먼저}
class Burger {
 final String name;
 Burger(this.name);
}
class CheeseBurger extends Burger {
 CheeseBurger(String name) : super(name) {
 } // 자식 생성자의 내부 스택이 실행되기 전에 먼저 부모 생성자에게 값을 전달

}
void main(){
 CheeseBurger cb = CheeseBurger("치즈햄버거");
 print(cb.name);

생성자

https://nomad-programmer.tistory.com/264


이름 있는 생성자

말 그대로 생성자에 이름을 부여한 형태.
한 클래스 내에 많은 생성자를 생성하거나 생성자를 명확히 하기 위해 사용한다.
기존의 기본 생성자는 단 하나만 가질 수 있다.
또한 이름 있는 생성자를 선언하면 기본 생성자는 생략할 수 없다.

클래스명.생성자명() {}

mixin / with


// 컴포지션
class Engine {
 int power = 5000; // 5000 cc
}
class BMW{
 Engine engine; // 엔진을 재사용하기 위해 컴퍼지션한 코드
 BMW(this.engine);
}
void main(){
 BMW b = new BMW(Engine());
 print(b.engine.power); // 결과 5000
}




// 믹스인
mixin Engine {
 int power = 5000; // 5000 cc
}
class BMW with Engine{
}
void main(){
 BMW b = new BMW();
 print(b.power); // 결과 5000
}

map

 List<String> chobab = ["새우초밥", "광어초밥", "연어초밥"];
 List<String> chobabChange = chobab.map((i) => "간장_$i").toList();
 print(chobabChange); // [간장_새우초밥, 간장_광어초밥, 간장_연어초밥]

where

filter와 비슷하다

 List<int> num = [1,2,3,4];
 List<int> num2 = num.where((i) => i%2==0).toList();
 print("짝수:$num2"); // 짝수:[2, 4]

spread

스프레드 흩뿌리기

값을 가지고 있는 컬렉션 깊은 복사
void main() {
 List<int> list = [1,2,3];
 List<int> newList = [...list];

 newList[0] = 500;
 print(list); // [1, 2, 3]
 print(newList); // [500, 2, 3]
} 

List 내부의 Map 데이터 자체가 레퍼런스를 참조하고 있어서,
그냥 ...list 로는 내부의 Map은 깊은 복사가 안된다

 List<Map<String,int>> list = [ {"id": 1,"age": 24, "money":500}, {"id": 2, "age": 33, "money":1000} ];
 List<Map<String,int>> shallowList = [...list];
 List<Map<String,int>> deepList = list.map((i) => {...i}).toList();

list[0]["money"] = 0;

 print(list); // [{id: 1, age: 24, money: 0}, {id: 2, age: 33, money: 1000}]
 print(shallowList); // [{id: 1, age: 24, money: 0}, {id: 2, age: 33, money: 1000}]
 print(deepList); // [{id: 1, age: 24, money: 500}, {id: 2, age: 33, money: 1000}]

 List<Map<String,dynamic>> users = [
 {"id":1, "username":"cos", "password":1234},
 {"id":2, "username":"ssar", "password":5678},
 ];

 // id가 2면 먼저 user를 흩뿌리고 username을 love로 덮어쓴다
 List<Map<String,dynamic>> newUsers = users.map(
 (user)=> user["id"] == 2 ? {...user, "username": "love"} : user
   // 
 ).toList();

 print(users);
 print(newUsers);

final / const

final은 런타임에 결정되는 값을 가지며,
const는 컴파일 시점부터 반드시 정해져 있어야하는 상수.
클래스 멤버로 사용할 때는 final이 주로 선택되고, 상수를 만들 때는 const를 사용합니다.

const : 컴파일 시에 초기화되기 때문에 런타임 때 속도가 빠르다.
동일한 클래스를 객체로 여러 번 만들어야 하는 경우에 생성자 인수의 값이 동일하면 같은 객체이기 때문에 메모리에 만들어진 객체를 재사용한다.

class Animal{
 final String name;
 const Animal(this.name); // 상수 생성자. 상수처럼 똑같은 객체를 생성함. 모든 변수가 final이고 생성자에 const가 붙어야 함.
}

void main(){
 Animal a1 = const Animal("사자");
 Animal a2 = const Animal("사자");
 Animal a3 = const Animal("기린");
 Animal a4 = const Animal("기린");

 print(a1.hashCode); // 316194174
 print(a2.hashCode); // 316194174
 print(a3.hashCode); // 1046960748
 print(a4.hashCode); // 1046960748
}

profile
https://github.com/k7850

0개의 댓글

관련 채용 정보