내가 보고 공부하려고 정리하는 Dart문법!
dart 문법 매뉴얼과 flutter 생존 코딩 공부 책을 보면서 정리.
dart.dev/guides/language/language-tour
A tour of the Dart language
A tour of all of the major Dart language features.
dart.dev
실습 가능한 웹 IDE 환경 : dartpad.dev/
DartPad
dartpad.dev
기본 문법
(티스토리 코드블럭은 Dart를 지원하지 않아 우선 java로 표기합니다)
주석
|
//주석
|
|
|
|
/**
|
|
* 주석
|
|
**/
|
|
|
|
/// 문서주석
|
문장
명령 단위. 세미콜론 ;으로 끝난다.
변수
data를 담는 상자. 종류는 type, 자료형이라고 함.dart는 int, double, String, bool을 기본 제공.사용자가 직접 타입을 정의할 수 있음.
|
String name;
|
|
name = "홍길동";
|
|
name = '홍길동';
|
|
//따옴표 종류 상관없이 가능
|
int, double은 num type의 하위 집합이라 int, double 대신 num으로 선언 가능.
num 타입에는 int, double 대입 가능.
|
int a = 1;
|
|
double b = 2.0;
|
|
|
|
num c = a;
|
|
c = b;
|
타입 추론
위와 같이 type을 직접 명시하지 않고, var로 대체할 수 있음. (JS같이)
일반적으로 많이 사용.
|
var i = 10; //int
|
|
var d = 10.0 //double
|
|
var s = "hello"; //String
|
|
var b = true; //boolean
|
상수 final, const
값이 변하지 않는 경우는 상수 사용. 선언시 final을 제일 앞에 붙이면 값이 수정되지 않음. 타입 생략 가능.
|
final String name = "홍길동";
|
|
final name = "홍길동";
|
산술 연산자
+, -, *, /(나누기 - double), ~/(몫 - int), %(나머지 - int) 사용 가능.
+의 경우 string concat에서도 사용.
증감 연산자
1씩 증가(++) 또는 1씩 감소(--). 후위(식++)/전위(++식) 연산 모두 가능.
비교 연산자
==, !=, >, <, >=, <= 사용 가능.
논리연산자
boolean 타입으로 결과 반환.
&&, ||, ==, !, != 사용 가능.
타입 검사
is를 사용.
[변수] is [type] => 같은 타입인지[변수] is! [type] => 다른 타입인지
|
int a = 1;
|
|
|
|
if (a is int){~}
|
|
if (a is! int){~}
|
형변환 (as)
type casting. as를 사용. 다른 타입끼리는 변환 불가. 상위 개념으로만 변환 가능.
특히, int, double은 num으로 묶여있지만 각자는 관계가 없어 형변화 불가.
|
var c = 10.0
|
|
num n = c as num;
|
|
num n = c //as num 생략 가능
|
|
int d = c as int; //errpr
|
함수
function. 코드 묶음 단위.
함수 형태
입력 받는 문자 : 매개변수 parameter실제로 입력받는 값 : 인수 argument반환되는 값 : 반환값 Return
=> 일반적인 C문법과 동일하다.
변수 앞에 $를 붙여 문자열 내에 변수 삽입 가능. (파이썬에서 {}사용하는 것과 같다)
또한, ${~~}부분에 표현식 사용 가능.
|
String name = "이순신";
|
|
int age = 20;
|
|
|
|
void main(){
|
|
print('$name은 $age살 입니다.');
|
|
print("$name은 ${name.length}글자 입니다.");
|
|
}
|
함수와 메서드
최상위 함수 : class 밖에 작성하는 함수. 일반적으로 말하는 함수들. (main method처럼 가장 밖에 작성). 어디에서나 호출 가능.
method : class 내부에 작성하는 함수. 정의된 class에 관계된 기능을 수행. Static이 붙은 method는 정적 메서드가 되어 최상위 함수처럼 사용 가능.
익명 함수
anonymouse function.
([인수명]) { [동작 or Return 값] }
|
(number) {
|
|
return number % 2 == 0;
|
|
};
|
람다식
([인수명]) => [동작 or Return 값]
(number) => number%2 == 0;
선택 매개변수
정의에서 {}로 감싼 매개변수는 선택적으로 사용 가능. Named parameter.
void f(String name, {int age}) {}
{}로 감싸지 않은 매개변수를 필수적으로 넘겨주어야 하고, {}로 감싼 매개변수에 값을 주고 싶다면 반드시 매개변수의 이름을 붙여서 age : 5로 넘겨주어야 한다.
선택 매개변수는 기본값 지정이 가능하다.
void f(String name, {int age = 5}) {}
분기와 반복
if else
|
int a = 10;
|
|
|
|
if (a % 2 == 0) {~}
|
|
else if (a % 3 == 0) {~}
|
|
else {~}
|
삼항 연산
[조건] ? [참일 때] : [거짓일 때]
var number = a%2 ? a++ : a--
switch case
조건에 맞는 값이 여러 개일 때 유용. enum과 함께 사용할 땐 모든 케이스를 검사해야 하는 강제성이 생김.
Switch - case - break로 문법은 C와 동일
for
요소를 반복.
|
for (var i = 0; i < 10 ; i++){
|
|
print(i);
|
|
}
|
객체 지향 프로그래밍
dart는 객체지향 프로그래밍 언어!
클래스
객체 object : 저장 공간에 할당되어 값을 가지거나 식별자에 의해 참조되는 공간. (변수, 함수, 메서드)
인스턴스 instance : 객체를 메모리에 작성하는 것.
클래스 class : 인스턴스의 설계도.
속성 property : 클래스 안에 표현되는 속성.
클래스는 일종의 사용자 정의 타입!
|
class Person{
|
|
String name;
|
|
int age;
|
|
}
|
|
|
|
var person = new Person();
|
|
var person2 = Person(); //new 생략 가능
|
변수명 뒤에 . 연산자를 입력, 객체의 property에 접근 가능.
|
print(person.name);
|
|
print(person.age);
|
메서드 : 클래스 안에 작성하는 함수. 메서드는 class의 프로퍼티를 조작하는 등의 용도로 사용. 이 역시 .연산자를 붙여 접근 가능.
접근 지정자
java에서의 public, private와 같은 역할. 여기서는 _ 을 붙여 구분한다. (붙이면 private)
|
class Person{
|
|
String name;
|
|
int _age;
|
|
|
|
void addOneYear(){
|
|
_age++;
|
|
}
|
|
}
|
|
|
|
//=====다른 Dart file
|
|
import 'person.dart';
|
|
|
|
void main(){
|
|
var person = Person();
|
|
person._age = 10; //error!
|
|
}
|
이때, private의 영역은 정의된 파일 내! 즉, _이 붙어 있어도 같은 파일 내라면 class의 밖에 있어도 자유롭게 접근이 가능하다.
생성자
인스턴스화 하는 방법을 제공하는 일종의 메서드. 인스턴스가 생성될 때 가장 먼저 생성됨. 메서드 이름은 클래스명과 같다.
|
class Person{
|
|
String name;
|
|
int _age;
|
|
|
|
Person({this.name, this._age}); //constructor
|
|
}
|
|
|
|
var person = Person();
|
|
var person2 = Person(name : '홍길동', _age : 20);
|
getter, setter
_을 붙인 private 변수에 외부에서 접근하기 위해 만들어주는 통로같은 메서드.
|
//person.dart
|
|
|
|
class Person{
|
|
String name;
|
|
int _age = 10;
|
|
|
|
int get age => _age; //getter
|
|
set setAge(num value) => _age = value; //setter
|
|
}
|
|
|
|
//main.dart
|
|
|
|
void main(){
|
|
var person = Person();
|
|
print(person.age); //10
|
|
person.setAge = 5;
|
|
print(person.age); //5
|
|
}
|
상속
implement. 주는 쪽이 super class (부모), 받는 쪽이 sub class(자식)
|
//부모 class
|
|
class Hero{
|
|
String name = 'hero';
|
|
|
|
void run() {}
|
|
}
|
|
|
|
//위를 상속받은 자식 클래스
|
|
class SuperHero extend Hero{
|
|
//재정의
|
|
void run(){
|
|
super.run(); //부모의 run실행
|
|
this.fly(); //추가로 자식이 따로 정의한 fly도 실행.
|
|
}
|
|
|
|
void fly() {}
|
|
}
|
|
|
|
|
|
void main(){
|
|
var hero = SuperHero();
|
|
hero.run();
|
|
hero.fly();
|
|
print(hero.name); //hero 출력
|
|
}
|
추상 클래스
abstract class. 추상 메서드를 포함하는 클래스.
추상 메서드 : 선언만되고 정의가 없는 메서드.
추상 클래스는 다른 클래스에서 implement해서 완성하는 상속 재료로 사용된다. (틀같은 느낌? 템플릿?)
이때 대상 클래스에는 implements, 메서드에는 @override 키워드 사용(
여러 추상 클래스를 한번에 implement할 수도 있고, 추상 클래스를 구현할 때는 모든 추상 메서드를 재정의 해야 한다.
|
abstract class Monster{
|
|
void attack();
|
|
}
|
|
|
|
abstract class Flyable{
|
|
void fly();
|
|
}
|
|
|
|
class Bat implements Monster, Flyable(
|
|
@override
|
|
void attack(){
|
|
print('할퀴기!');
|
|
}
|
|
|
|
|
|
void fly(){
|
|
print('펄럭펄럭');
|
|
}
|
|
}
|
믹스인
mixin. with를 사용하면 상속하지 않고 다른 클래스 기능 overwritte가능.
|
class Goblin implements Monster{
|
|
|
|
void attack(){
|
|
print('고블린 공격');
|
|
}
|
|
}
|
|
|
|
class DarkGoblin extends Goblin with Hero{
|
|
|
|
} //다크 고블린은 고블린이기도 하며, 히어로이기도 하며, 몬스터이기도 함. => 다형성!
|
열거형
enum type. 상수를 정의하는 특수한 형태의 클래스. 상수처럼 사용이 가능하다.
|
enum Status { login, logout }
|
|
|
|
var authStatus = Status.logout;
|
|
|
|
switch(authStatus){
|
|
case Status.login:
|
|
print('login');
|
|
break;
|
|
case Status.logout:
|
|
print('logout');
|
|
break;
|
|
}
|
컬렉션
list, map, set등의 collection을 기본 제공함.
List
순서가 있는 자료를 담음. Dart는 배열 (Array)를 별도로 제공하지 않는다.
|
List<String> items = ['a', 'b', 'c'];
|
|
var items = ['a', 'b', 'c'];
|
|
|
|
items[0] = 'd'; //0부터 시작하는 index.
|
|
|
|
print(items.length); //3
|
※ dynamic
모든 타입을 대변하는 특수 타입! 여러 타입을 한 리스트에 넣거나 일반 변수를 선언할 때도 사용 가능.
List<dynamic> list = [1, 2, 'a'];
var list = [1, 2, 'a'];
스프레드 연산자
spread. '...' 연산자. 컬렉션을 펼쳐준다. 다른 컬렉션 안에 컬렉션을 삽입할 때 사용.
|
var items = ['a', 'b', 'c'];
|
|
|
|
var items2 = ['d', ...items, 'e']; //d, a, b, c, e
|
Map
순서 없음. 탐색 빠른 자료구조. key-value의 쌍.
|
//Map<String, String> cityMap = {...} 과 같음.
|
|
var cityMap = {
|
|
'korea': 'busan',
|
|
'japan': 'tokyo',
|
|
'china': 'Beijing'
|
|
};
|
|
|
|
cityMap['korea'] = 'seoul';
|
|
|
|
print(cityMap.length); //3
|
|
|
|
cityMap['America'] = 'Washington'; //새 값 추가
|
Set
집합 표현. => 중복 불허용
add(), remove()로 추가/삭제 가능.
contains() : 찾는 자료가 집합에 있는지 없는지 bool로 반환.
|
// Set<String> citySet = {}과 같음
|
|
var citySet = {'서울', '부산', '광주', '대전', '울산'}
|
|
|
|
citySet.add('대구');
|
|
citySet.remove('서울');
|
|
|
|
print(citySet.contatins('울산'); // true
|
비어있는 Set이나 map을 작성할 때는 주의! 그냥 {}만 쓰면 Map으로 인식해버림.
|
var mySet = <String>{}; //set으로 인식
|
|
var mySet2 = {}; //dynamic, dynamic인 map으로 인식
|
함수형 프로그래밍
Dart는 객체지향 프로그래밍과 함수형 프로그래밍의 특징을 모두 제공 (뭐지....)
함수형 프로그래밍 : 자료 처리를 수학적 하수의 계산으로 취급하는 패러다임. (상태와 가변 데이터 X)
일급 객체
함수를 값으로 취급. 즉, 다른 변수에 함수를 대입할 수 있음.
|
void greeting(String text){
|
|
print(text);
|
|
}
|
|
|
|
void main(){ // 함수를 다른 변수에 대입할 수 있음
|
|
var f = greeting;
|
|
f('hello');
|
|
}
|
다른 함수의 인수로 함수 자체를 전달하거나 함수를 반환받을 수도 있음.
함수를 매개변수로 전달, 수정, 변수에 대입하기가 가능한 객체를 '일급 객체', first-class object라고 함.
for문과 forEach()함수
for : 외부 반복
forEach() : 내부반복 =>(E element) {} 형태의 함수를 인수로 받음.
|
items.forEach(print); // 1, 2, 3, 4, 5
|
|
|
|
items.forEach((e) {
|
|
print(e);
|
|
});
|
|
|
|
itmes.forEach((e) => print(e));
|
|
|
|
items.forEach(print);
|
where
조건을 필터링 할 때 사용. 함수형 프로그래밍을 지원하는 함수들은 결과를 반복 가능한 타입으로 반환하여 메서드 체인으로 연결해서 사용 가능.
items.where((e) => e % 2 == 0).forEach(print); //2, 4
map
반복되는 값을 다른 형태로 변환하는 방법을 제공.
items.where((e) => e % 2 == 0).map((e) => '숫자 $e').forEach(print);
toList
함수형 프로그래밍을 지원하는 함수 대부분은 Iterable<T> 인터페이스 타입 인스턴스를 반환.
하지만 실제 사용할 때는 대부분 리스트 형태로 변환해야 하는 경우가 많음. => 결과를 리스트로 바꿔야함.
final result = itmes.where((e) => e % 2 == 0).toList();
toSet
리스트에 중복된 데이터가 있을 경우, 중복을 제거한 리스트를 얻고 싶을 때 집합인 set을 사용.
final result = itmes.where((e) => e % 2 == 0).toSet().toList();
any
리스트에 특정 조건을 충족하는 요소가 있는지 없는지 검사할 때 사용하는 함수.
print(items.any((e) => e % 2 == 0));
reduce
반복 요소를 줄여가면서 결과를 만들 때 사용하는 함수.
|
// 최댓값을 구할 때, 순차적으로 비교하는 로직
|
|
|
|
final result = items.reduce(max); //5
|
기타
계단식 표기법 .. 연산자
cascade notation .. 연산자. 동일 객체에서 일련의 작업을 수행 가능.
.. 연산자를 사용하면 메서드를 수행한 객체의 참조를 반환.
|
print(items
|
|
..add(6)
|
|
..remove(2)); //1, 3, 4, 5, 6
|
컬렉션 if
조건에 의해 컬렉션의 값을 조정하거나 다르게 사용하고 싶을 때 사용.
|
bool promoActive = true;
|
|
|
|
print([1, 2, 3, 4, 5, if (promoActive) 6]); // true일 때만 6이 추가됨
|
컬렉션 for
컬렉션 문법 안에서 for 문을 사용 가능.
|
var listOfInts = [1, 2, 3];
|
|
var listOfStrings = [
|
|
'#0',
|
|
for (var i in listOfInts) '#$i'
|
|
];
|
|
//#0, #1, #2, #3
|
null 처리
다트는 null을 처리할 수 있는 여러가지 방법을 제공. (Dart에서는 모든 것이 객체. int, double, bool 같은 타입들도 모두 객체라 null값을 가질 수도 있음.)
?. 연산자를 사용하면 null 여부 파악 가능.
print(name?.lentgh); //null출력
??연산자는 객체가 null일 때 작동을 간단히 구현하는데 사용.
print(name?.length ?? 0); //name이 null이면 0을 출력
출처: https://at0z.tistory.com/155 [💾:티스토리]
'flutter' 카테고리의 다른 글
라이프 사이클 (0) | 2022.11.09 |
---|---|
bottomnavigationbar를 유지하는 방법 (0) | 2022.10.28 |