[Dart/Flutter] 콜렉션(Collection)과 제네릭(Generic)

ryan·2021년 9월 27일
2

Dart/Flutter

목록 보기
13/21
post-thumbnail

링크

Collection과 Generic

1. String interpolation

$a 님 반갑습니다 => 홍길동님 반갑습니다
$b 님 반갑습니다 => 코딩셰프님 반갑습니다

  • Interpolation: 보간법, 문자열을 출력하거나, 선언할 때, 중간중간에 다른 변수를 끼워넣는 것

    당신의 점수는 $score이며 당신의 레벨은 $level입니다

void main() {
  String name = 'Sean';
  print(name); // Sean
  
  // $name : dart야, 내가 name이라는 변수를 여기에서 사용할테니,
  // 너는 출력할 때 이걸 보고 이 자리에다 변수 값을 넣어서 출력해줘
  print("Hi, $name, what's up?"); // Hi, Sean, what's up?
}

Collection과 제네릭

  • Collection: 데이터들을 모아서 가지고 있는 자료구조
  • Generic: Collection이 가지고 있는 데이터들의 데이터 타입을 지정해서 코드의 안전성을 확보하고, 코드의 재사용성을 가능하게하는 기법이다

코드 분석

void main() {
  // fixed-length list: list 내의 데이터의 갯 수가 지정한만큼만 올 수 있다
  // new List(5);
  // 위와 같이 number가 있으면 fixed-length list, 없으면 growable list
  // -------------------------------------------------------------
  // 코드 분석
  // new List는 List 클래스의 생성자를 통해서, 새로운 인스턴스를 생성한 것
  // 그리고 이 인스턴스를 number라는 변수에 할당한 것
  // 즉, 변수 number가 List 객체의 참조를 저장하고 있다라고 표현할 수 있다
  // var 키워드를 사용해서 변수를 사용하면, 해당 변수, 즉 number가
  // 참조하고 있는 객체에 따라서 타입이 결정된다
  // 그래서 변수 number 현재 타입은 List타입이 된다
  // 즉, Dart가 알아서 해당 변수가 참조하고 있는 객체를 통해 타입을 추론한다는 것
  var number = new List(5);
  
  // 그렇다면 var 키워드 대신에 직접 알맞은 타입을 지정해주어도 문제가 없어야한다
  List number2 = new List();

  // growable list: list 내의 데이터의 갯 수에 제한이 없다
}

dynamic 키워드

void main() {
  // List<dynamic>number
  // dynamic 키워드는 어떤 변수가 여러 타입으로 지정될 수 있어야할 때, 사용한다
  List number = new List();
  // List에 데이터를 추가할 때는 add 함수를 사용한다
  number.add(2);
  number.add('test');
  number.add(7.4);

  print(number); // [2, test, 7.4]
}

Dart와 객체 그리고 제네릭 타입

// Dart에서는 변수에 넣을 수 있는 모든 것을 객체로 취급한다
// 즉, List 안에서 데이터로 나열될 수 있다는 의미이다
// 더 나아가, Dart에서는 함수나 boolean 값도 객체로 취급해서
// List에 넣을 수 있다

int addNumber(int num1, int num2) {
  return num1 + num2;
}

void main() {
  // <>anchor bracket 괄호가 제네릭 타입임을 나타낸다
  // <>안에 리스트에 들어올 데이터들의 타입을 지정해주면된다
  List<dynamic> number = new List();
  
  number.add(2);
  number.add('test');
  number.add(7.4);
  number.add(addNumber(3, 4));
  number.add(true);
  print(number); // [2, test, 7.4, 7, true]
}

제네릭 타입에 int 지정

int addNumber(int num1, int num2) {
  return num1 + num2;
}

void main() {
  List<int> number = new List();
  
  number.add(2);
  number.add('test'); // error
  number.add(7.4); // error
  number.add(addNumber(3, 4));
  number.add(true); // error
  print(number);
}

Why? 불편하게 타입 지정?

// dynamic으로 항상 제니릭 타입으로 구현하면
// 일일히 타입에 신경 쓸 필요도 없고, 편할텐데
// 왜 코딩할 때, 컬렉션 제네릭 타입을 구체적으로 정해줘야 좋을까요?
// A. 코드의 안정성

void printNumber(List<int> a) {
  print(a);
}

void main() {
  // List<dynamic>이어서 타입이 일치하지않기때문에 에러가 발생한다
  // List<int> number = List();를 사용하면 문제 없이 함수가 실행된다
  List<dynamic> number = List();
  number.add(5);
  printNumber(
      number); // error: Uncaught Error: TypeError: Instance of 'JSArray<dynamic>': type 'JSArray<dynamic>' is not a subtype of type 'List<int>'
}

예제

void main() {
  // 컬렉션을 구현할 때, 제네닉 타입은 가급적 var키워드나 dynamic 키워드를 사용하지말고,
  // 구체적인 타입으로 지정해서 사용하는 것이 바람직하다
  // List<dynamic> names = List();
  List<String> names = List();
  
  // addAll 함수를 사용하면 다양한 요소를 추가할 수 있다
  names.addAll(['James', 'John', 'Tom']);
  
  print(names); // [James, John, Tom]
}
profile
👨🏻‍💻☕️ 🎹🎵 🐰🎶 🛫📷

0개의 댓글