본문 바로가기
Develope_Web&App/04_Android

2장 : 다트 문법

by 스타트업_디벨로퍼 2021. 2. 9.

2.1 다트 언어 연습 환경

DartPad
http://dartpad.dev
void main() { print("Hello,World!"); }

2.2 기본 문법

2.2.1 주석

// 이것은 주석 /** *이것도 주석 **/ /// 이것도 주석 void something() {}
💡
///를 메서드나 클래스 정의 위에 작성하면 dartdoc과 같은 문서 생성 도구를 통해 문서를 자동으로 생성해줍니다.

2.2.2 문장

문장은 명령 단위이며 문장 끝은 세미 콜론으로 표시한다.!!

2.2.3 변수

변수는 데이터를 담는 상자입니다. 변수 종류를 타입 또는 자료형이라고 합니다. 다트는 숫자나 문자열 같은 기본 변수 타입을 제공하며, 사용자가 직접 타입을 정의함.

💡
int : 정수 double : 실수(소수점) String : 문자열 bool : 참 또는 거짓 값을 갖는 타입

문자열은 작은 따옴표와 큰따옴표를 모두 사용할 수 있음.

String name; name = "홍길동; //name = '홍길동'; 
bool b= true; bool b2 = i<10; bool b3 = s.isEMpty;
💡
int와 double이 있는데 num이 이를 모두 포함한다. dart에서는 double을 지원하지 않는다.

변수에 담긴 값은 언제라도 다른 값으로 바꿀 수 있다.

2.2.4 타입 추론

💡
다트는 타입을 직접 명시하지 않고 var로 대체할 수 있는 타입 추론을 지원함.
var i = 10; var d = 10.0; var s = 'hello'; var s2 = "hello"; var b = true;

2.2.5 상수 final, const

💡
의도치 않게 에러를 발생할 수 있으므로 값이 변하지 않도록 상수를 사용하는 것이 좋으며, final 을 붙이게 된다.
final String name = '홍길동'; 

2.2.6 산술 연산자

💡
+ : 더하기, - : 빼기, * : 곱하기, / : 나누기 , ~/ : 몫, % : 나머지
💡
assert() 함수는 계산 결과가 참인지 검사합니다.

2.2.7 증감 연산자

💡
증감 연산자는 1씩 증가하거나 감소시키는 연산자로 후위 연산과 전위 연산이 있습니다.

2.2.8 비교 연산자

💡
== : 같다, ! = 다르다. > 크다 < 작다. > = 크거나 같다. < = 작거나 같다

2.2.9 논리 연산자

💡
&& : 그리고, || : 또는, == : 같다, ! : 부정

2.2.10 타입 검사

int a = 10; if (a is int) { print('정수'); } String text = 'hello'; if (text is! int) { print('숫자가 아님'); }

2.2.11 형변환(as 키워드)

var c = 30.5; int d = c as int;

2.3 함수

2.3.1 함수 형태

int f(int x) { return x + 10; } void main() { var result = f(10); } 

매개변수를 두개 이상을 넣을 수도 있고, return 타입을 String로도 구현이 가능하다. 또한 void처럼 없이도 가능하다!

void greeting(String greet) { print('hello $greet'); } greeting(String greet){ print('hello $greet); }
💡
$ 기호를 붙여 문자열 내에 변수를 삽입할 수 있음. $ 기호 뒤에 {}로 둘러싸 수식을 포함한 각종 표현식을 사요할 수 있음.
String _name = '홍길동'; int _age = 20; void main() { print('$_name은 $_age살입니다.'); print('$_name은 $글자입니다.'}; print('10년 후에는 $살입니다.'); } 

2.3.2 함수와 메서드

💡
최상위 함수(일반적으로 main())는 어디에서나 호출할 수 있는 함수이며 이 책에서 함수라고 칭하는 대부분은 최상위 함수를 가리킵니다. / 클래스 내부에 작성하는 함수를 메서드라고 부르며, 정의된 클래스에 관계된 기능을 수행함.

💡
클래스 내부에 선언된 함수이더라도 static 키워드를 붙이면 정적 메서드가 되며 함수로 볼 수 있음. static 키워드가 붙은 함수는 최상위 함수처럼 사용할 수 있음.

2.3.3 익명 함수

([인수명]) {[동작 또는 반환값]}
💡
이름 없는 익명함수도 정의해 사용할 수 있음.
(number){ return number % 2 == 0; } 

2.3.4 람다식

💡
다트에서는 람다표현식이라는 함수 표현 방식을 지원함. 왼쪽에는 인수명을 작성하고, 오른쪽에서는 동작할 코드 또는 반환값을 작성함. ([인수명]) ⇒ [동작 또는 반환값]

2.3.5 선택 매개변수

💡
{}로 감싼 매개변수는 선택적으로 사용할 수 있음.
void something({String name, int age}) {} //{} 쳐준 부분만 선택이라 안하면 에러난다!  void main() { something(name: '홍길동', age:10); something(name: '홍길동'); something(age:10); something(); }

void something(String name, {int age = 10}) {} void main() { something('홍길동', age: 10); something('홍길동'); //기본값 지정되어 동일한 값 }

2.4 분기와 반복

💡
if / else, 삼항 연산, switch case, for 는 생략

2.5 객체 지향 프로그래밍

2.5.1 클래스

💡
객체는 저장 공간에 할당되어 값을 가지거나 식별자에 의해 참조되는 공간을 의미함. 변수, 자료 구조, 함수 또는 메서드 등이 객체가 도리 수 있음. 객체를 메모리에 작성하는 것을 인스턴스화한다고 하며 메모리에 작성된 객체를 인스턴스라고 함. 인스턴스화하기 위해서는 설계도가 필요한데 설계도 역할을 하는 것이 클래스 클래스 안에 속성을 표현하는 것이 프로퍼티(property)라고 함.

class Person{ String name; int age; void addOneYear() { age++; } } void main() { var person = new Person(); person.age = 10; person.name = '박보검'; person.addOneYear(); print(person.name); }

2.5.2 접근 지정자

💡
변수명 앞에 _ 기호를 붙이지 않으면 외부에서 접근 가능하고, 붙이면 접근 불가능함.clc
class Person{ String name; int age; void addOneYear(){ age++; } } // main.dart import 'person.dart'; var person = Person(); person.age = 10; //접근 가능 

class Person{ String name; int _age; void addOneYear(){ _age++; } } // main.dart import 'person.dart'; var person = Person(); person._age = 10; //접근 불가!! 
💡
_ 기호가 붙은 프라이빗 변수는 해당 클래스가 정의되어 있지 않은 다른 파일에서 직접 접근할 수 없음.

2.5.3 생성자

💡
생성자는 인스턴스화하는 방법을 제공하는 일종의 메서드. 다트는 기본 생성자를 제공하는 데 기본 생성자는 클래스명과 같은 이름의 메서드
class Person { String name int _age; var person = Person(); }
💡
사용자 정의 생성자를 추가하면 기본 생성자를 사용할수 없게 되지만, 선택 매개변수를 사용하면 Person()도 호출할 수 잉ㅆ음.
class Person { String name; int _age; Person({this.name, this._age}); //생성자 var person = Person(); var person2 = Person(name: '홍길동', _age;20); }

2.5.4 게터와 세터

💡
프라이빗 변수에 접근하려면 게터와 세터 메서드가 필요함.
class Person { String name; int _age; int get age => _age; } //main.dart import 'person.dart' var person = Person(); print(person.age); //_age 값이 출력됨. 

💡
게터는 프라이빗 변수값에 변경을 주어 사용할 떄도 유리함. 프로퍼티끼리 직접 계산하는 방식보다 게터와 세터를 이요해 계산하는 방식이 코딩 실수로 발생하는 오류를 줄일 수 있음.

class Rectangle { num left, top, width, height; Rectangle(this.left, this.top, this.width, this.height); num get right => left + width; set right(num value) => left = value - width; num get bottom => top + height; set bottom(num value) => top = value - height; }

2.5.5 상속

💡
extends 키워드를 사용하여 상속받아 새로운 기능을 추가할 수 있으나 새로 정의하고 싶다면 @override 어노테이션을 사용해 오버라이드하여 재정의하면 됨 이떄 super 키워드를 사용하면 슈퍼클래스에 접근할 수 있음. 나 자신을 참조할 때는 this를 사용할 수 있지만 일반적으로 생략함.
class Hero { Strubg name = '영웅'; void run() {} } class SuperHero extends Hero {  void run() { super.run(); this.fly(); } void fly(){} } void main() { var hero = SuperHero(); hero.run(); hero.fly(); print(hero.name); }
💡
상속은 기존 기능을 재정의할 때 사용함.

2.5.6 추상 클래스

💡
추상 클래스는 추상 메서드를 포함하는 클래스 → 다른 클래스에서 임플먼트하여 기능을 완성하는 상속 재료로 사용됨.

2.5.7 믹스인

💡
with 키워드를 사용하면 상속하지 않고 다른 클래스의 기능을 가져오거나 오버라이드할 수 있음. 이러한 기능을 믹스인이라고 함.
class Goblin implements Monster {  void attack() { print('고블린 어택'); } } class DarkGoblin extends Goblin with Hero{ }

3.5.8 열거 타입

💡
열거 타입은 상수를 정의하는 특수한 형태의 클래스임. 열거 타입은 상수처럼 사용할 수있음. switch 문과 함께 사용하면 열거 타입으로 정의된 모든 상수를 case로 검토하도록 강제하기 때문에 에러를 방지하는 효과도 있음.
var authStatus = Status.logout; switch(authStatus) { case Status.login; print('로그인'); break; case Status.logout; print('로그아웃'); break; } 

2.6 컬렉션

💡
다트는 List, Map, Set 등의 컬렉션을 제공함. List : 같은 타입의 자료를 여러 개 담을 수 있고 특정 인덱스로 접근할 수 있음. Map : 키와 값의 쌍으로 저장할 수 있고 키를 통해 값을 얻을 수 있음. Set : 중복이 허용되지 않고, 찾는 값 이 있는지 없는지 판단하고자 할 때 사용함

2.6.1 List

💡
List는 순서가 있는 자료를 담는 컬렉션임. 다른 언어에서는 배열과 리스트가 별도로 제공되지만, 다트는 배열에 제공하지 않습니다.
List<String> items = ['짜장', '라면', '볶음밥']; //일반적으로 var로 선언함.

var items = ['짜장', '라면', '볶음밥']; items[0] = '떡볶이'; for (var i = 0; i< items.length; i++) { print(items[i]); } 

2.6.2 스프레드 연산자

💡
연산자는 컬렉션을 펼쳐주는 연산자로 스프레드 연산자라고 함. 다른 컬렉션 안에 컬렉션을 삽일할 때 사용함
var itesms = ['짜장', '라면', '볶음밥']; var items2 = ['떡볶이', ...items, '순대']; -> 세트에 담게된다면 중복 제거도 가능함.

2.6.3 Map

💡
순서가 없고 탐색이 빠른 자료구조 컬렉션임. 키와 값의 쌍으로 이루어져 있어 키를 이용하여 값을 빠르게 얻을 수 있음. 요청한 키에 해당하는 값이 없다면 값 없음을 의미하는 null을 반환함.

var cityMap = { '한국' : '부산', '일본' : '도쿄', '중국' : '북경' }; cityMap['한국'] = '서울'; print(cityMap.length); print(cityMap['중국']); print(cityMap['미국']); cityMap['미국'] = '워싱턴'; print(cityMap['미국']);

2.6.4 Set

💡
add(), remove()가 가능하다! contains() 메서드를 통해서 찾고자 하는 자료가 있는지 확인할 수 있다.

var citySet = {'서울', '수원', '오산','부산'}; citySet.add('안양'); citySet.remove('수원'); print(citySet.contains('서울')); print(citySet.contains('도쿄')); 

2.7 함수형 프로그래밍

💡
함수형 프로그래밍은 자료 처리를 수학적 함수의 계산으로 취급하는 프로그래밍 패러다임.

2.7.1 일급 객체 → 함수를 대입할 수 있음.(값 그자체)

void greeting(String text) { print(text); } void main() { var f = greeting; f('hello'); } 

다른 함수의 인수로 함수 자체를 전달하거나 함수를 반환받을 수도 있음.

void something(Function(int i)f){ f(10); } void main() { something((value){ print(value); }); }

💡
변수에 대입하기가 가능한 객체를 일급 객체라고 함. 함수로 표현할수 있는것들(람다식, 익명 함수, 메서드)은 모두 값으로 취급할 수 있음.

2.7.2 for 문과 forEach() 함수

forEach() 함수는 내부 반복을 수행합니다. (E element) {} 형태의 함수를 인수로 받습니다.

items.forEach(print); items.forEach((e) { print(e); });

2.7.3 where

final items = [1,2,3,4,5]; for (var i = 0; i< items.length; i++){ if(items[i] % 2 == 0 ) { print(items[i]); } } items.where((e) => e % 2 == 0).forEach(print);

→ 메서드 체인으로 연결하여 사용 가능함.

2.7.4 map

map() 함수는 반복되는 값을 다른 형태로 변환하는 방법을 제공하는 함수

fianl items = [1,2,3,4,5]; for (var i = 0; i< items.length; i++) { if(items[i]%2 == 0){ print('숫자 $'); } }
items.where((e) => % 2 == 0).map((e) => '숫자 $e').forEach(print);

2.7.5 toList

💡
함수형 프로그래밍을 지원하는 함수 대부분은 Iterable<T>라는 인터페이스 타입 인스턴스를 반환합니다.
final result = []; items.forEach((e) { if(e % 2 == 0) { result.add(e); } });

toList() 함수를 사용하면 간단히 리스트로 변환할 수 있음.

final result = items.where((e) => e%2 == 0).toList(); 
💡
toList() 함수는 where(), map()과 같이 Iterable 인터페이스를 반환하는 메서드에서 사용할 수 있음.

2.7.6 toSet

💡
리스트에 중복된 데이터가 있을 경우 중복을 제거한 리스트를 얻을 수 있음.

f

final items = [1,2,2,3,3,4,5]; var result = []; for (var i = 0; i<items.length; i++){ if(items[i]%2 == 0) { result.add(items[i]); } } print(result);

final result = items.where((e) => e % 2 == 0).toList();

final items = [1,2,2,3,3,4,5]; var result = []; var temp = <int>{}; for (var i = 0; i < items.length; i++){ if(items[i]&2 ==0){ temp.add(items[i]); } } result = temptoList(); print(result);
final result = items.where((e) => e%2 ==0).toSet().toList();

2.7.7 any

💡
any() 함수는 리스트에 특정 조건을 충족하는 요소가 있는지 없는지 검사할 때 사용함.
final items = [1,2,2,3,3,4,5]; var result = false; for (var i = 0; i<items.length; i++){ if(items[i] % 2 == 0) { result = true; break; } } print(result);
print(items.any((e) => e%2 ==0));

2.7.8 reduce

💡
reduce() 함수는 반복 요소를 줄여가면서 결과를 만들 때 사용

import 'dart:math'; final items = [1,2,3,4,5]; var maxResult = items[0]; for (var i = 1; i< items.length; i++){ maxResult = max(items[i], maxResult); } print(maxResult);

final items = [1,2,3,4,5]; print(items.reduce((e,v) => max(e,v)));

2.8 기타 유용한 기법

2.8.1 계단식 표기법 ..연산자

💡
.. 연산자를 사용하면 메서드를 수행한 객체의 참조를 반환함.

final items = [1,2,3,4,5]; var result = items; result.add(6); result.remove(2); print(result); print(itemss ..add(6) ..remove(2));

2.8.2 컬렉션 if

bool promoActive = false; if (promoActive) { print([1,2,3,4,5,6]); }else { print([1,2,3,4,5]); } bool promoActive = true; print([1,2,3,4,5, if (promoActive) 6]);

2.8.3 컬렉션 for

var listOfInts = [1,2,3]; var listOfStrings = [ '#0', for (var i in listOfInts) '#$1' ]; listOfStrings.forEach(print); 

2.8.4 null 처리에 관한 기능

💡
값이 없다는 의미의 null은 에러를 유발하기 쉬움.

if (name != null) { print(name.length); } print(name?.lenght);
💡
?. 연산자를 사용하면 객체가 null 일때 에러를 발생하는 대신 null을 반환함.

if (name != null) { print(name.length); } else { print(0); } print(name?.length ?? 0); //name이 null 이면 0을 출력

반응형