변수를 정의할 때 타입을 정하지 못하는 순간이 있다. 이때 그냥 var, const, final 등의 키워드로 타입을 정의하지 않고 지나가면 IDE가 컴파일 에러를 발견하지 못해 후에 런타임 에러가 나기 쉽다.
이러한 불상사를 방지하기 위해 제네릭을 사용해서 타입을 나중에 원하는 형태로 정의할 수 있다. 즉, type safe 효과를 위해 제네릭을 사용한다.
class StrongBox<E> {
E? _money;
void get(E money) {
_money = money;
}
}
void main() {
StrongBox box = StrongBox();
box.get("10000");
}
위 코드에서는 _money
변수에 "10000"이라는 String 값을 넣었고, 이 순간 _money
의 타입은 String이 된다. 여기서 int형 10000을 넣으면 변수의 타입은 int가 될 것이다. 이처럼 제네릭은 임시 자료형이라고 생각하면 된다.
또한, extends
를 사용해서 특정 타입만 E의 타입이 될 수 있도록 제한할 수 있다. 만약<E extends String>
였다면 _money
에 숫자 10000을 넣을 수 없을 것이다.
상수(const)의 집합 클래스이다. 이 클래스에 정의된 값들은 변하지 않는다. 각각의 상수에 대한 처리가 필요할 때 switch문을 사용한다. if문을 사용하지 않는 이유는 상수가 추가될 때 if문에 조건을 추가하지 않는 실수를 할 수 있는 반면 switch에서는 각각의 상수에 대한 처리를 하지 않으면 에러가 나므로 실수를 할 가능성을 줄인다.
enum KeyType {
padlock,
button,
dial,
finger
}
합치고자 하는 문자열 사이에 +를 넣는 방법이다. 가장 직관적이지만 계속 +로 문자열을 합치는 경우 합쳐진 결과물이 새로운 인스턴스로 메모리에 계속 할당되기 때문에 문자열이 만들어지는 속도가 느리다.
ex) print('Hello' + 'World')
문장에 변수를 넣어야 할 때 많이 사용되어지는 방법이다. ${수식} 형태로 + 기호 없이 변수를 문장에 바로 넣을 수 있다.
write() 메소드로 결합한 결과를 내부 메모리(버퍼)에 담아두고 toString으로 결과를 얻는 방법이다.
final buffer = StringBuffer('Dart');
buffer
..write(' and ')
..write('Flutter');
print(buffer.toString()); // Dart and Flutter
위 코드에서 ..
연산자는 cascade연산자로도 불리며, void 리턴인 함수의 앞에 사용하면 해당 객체의 레퍼런스를 반환하여 메서드 체인을 사용할 수 있게 해준다. buffer..write(' and ')
는buffer.write(' and ')
와 같은 코드이다.
void main() {
String greeting = 'Hello';
print(greeting.replaceAll('H', 'J'));
print(greeting);
}
// output: Jello
// Hello
indexOf(Pattern pattern, (int start))
: (start 인덱스부터) pattern이 어느 인덱스에 있는지 알려준다. 없다면 -1을 리턴한다.final string = 'HELLO';
print(string.indexOf('E')); // output: 1
length
: 문자열의 길이를 리턴한다.isEmpty
: 길이가 0인지 아닌지를 알려준다.contains(String a)
: a가 문자열에 포함되어 있는지 알려준다.endsWith()
& startsWith()
: 문자열이 ~로 끝나는지 / 시작하는지를 알려준다.indexOf()
: 단어가 몇 번째에 있는지를 알려준다.lastIndexOf()
: 뒤에서 몇 번째에 단어가 있는지를 알려준다.