ui 그리는 프레임워크
기반 언어 : 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이 가능하다
String s = null; // 오류
String? s = 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로 매개변수 선택해서 입력하기
}
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
말 그대로 생성자에 이름을 부여한 형태.
한 클래스 내에 많은 생성자를 생성하거나 생성자를 명확히 하기 위해 사용한다.
기존의 기본 생성자는 단 하나만 가질 수 있다.
또한 이름 있는 생성자를 선언하면 기본 생성자는 생략할 수 없다.
클래스명.생성자명() {}
// 컴포지션
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
}
List<String> chobab = ["새우초밥", "광어초밥", "연어초밥"];
List<String> chobabChange = chobab.map((i) => "간장_$i").toList();
print(chobabChange); // [간장_새우초밥, 간장_광어초밥, 간장_연어초밥]
filter와 비슷하다
List<int> num = [1,2,3,4];
List<int> num2 = num.where((i) => i%2==0).toList();
print("짝수:$num2"); // 짝수:[2, 4]
스프레드 흩뿌리기
값을 가지고 있는 컬렉션 깊은 복사
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를 사용합니다.
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
}