Dart 심화 문법 (class, list, map)

Updated:


1.class 선언 및 constructor

  • 비슷한 성격, 기능들의 변수와 함수를 모아 놓는것이 class 라고 합니다.

  • class 의 명을 항상 대문자로 시작합니다

void main() {
  // Instantiation 인스턴스화  class 를 instance 로 바꾸는것
  People yourName = People('Jacob', '학생');

  yourName.sayName(); // 제 이름은 Jacob 입니다 / 제 직업은 학생 입니다
  print(yourName.name); // Jacob
  print(yourName.group); // 학생

}

class People {
  String name;
  String group;

// constructor 생성 : class 가 처음 선언이 되었을때 원하는 변수를 class 안에 집어 넣을 수 있는 기능
  People(
    String name,
    String group,
  )   : this.name = name,
        this.group = group;

  void sayName() {
    print('제 이름은 ${this.name} 입니다');
    print('제 직업은 ${this.group} 입니다');
  }
}

Named constructor

  • Named constructor 를 사용하게되면 한 class 안에서 여러개의 constructor 를 생성할 수 있게 됨, class 를 여러가지로 인스턴스화 할 수 있다는 것입니다
void main() {
  // Instantiation 인스턴스화  class 를 instance 로 바꾸는것
  People yourName = People('Jacob', '학생');

  yourName.sayName(); // 제 이름은 Jacob 입니다 / 제 직업은 학생 입니다
  print(yourName.name); // Jacob
  print(yourName.group); // 학생

  People newMenber = People.fromMap({'name': 'John', 'group': '회사원'});
  newMenber.sayName(); //제 이름은 John 입니다 제 직업은 회사원 입니다
  print(newMenber.name); // John
  print(newMenber.group); // 회사원
}

class People {
  String name;
  String group;

// constructor 생성 : class 가 처음 선언이 되었을때 원하는 변수를 class 안에 집어 넣을 수 있는 기능
// final 을 사용하게 되면 class 안에서 무조건 적으로 변수를 선언해야 되고, 그 해당 변수들은 class 안에 생성되게 되면 그 뒤로는 변수의 값을 바꿀 수 없게 할 수 있음
  People(
    final String name,
    final String group,
  )   : this.name = name,
        this.group = group;

  // Named constructor
  People.fromMap(
    Map input,
  )   : this.name = input['name'],
        this.group = input['group'];

  void sayName() {
    print('제 이름은 ${this.name} 입니다');
    print('제 직업은 ${this.group} 입니다');
  }
}

2.Getter and Setter

  • Getter -> 값을 가져올때

  • Setter -> 값을 변경할때

  • 변수에 _ underScore 를 붙이는 것을 Private variable 이라고 함. 이것을 왜 쓰냐면 전통적인 OOP 를 하는 Java 같은데서는 class 안에서만 private 변수들을 가져 올수 있습니다. 근데 dart 는 특이하게 같은 파일에서 작성이 되었을때만 private 변수를 가져 올 수 있습니다.

  • 만약 class 가 다른 파일에 있고, main 함수에서 class 를 import 해서 사용해야될 경우에 private 변수를 사용할때 error 가 발생됨

  • 그래서 그것을 가져오기 위해서 getter 와 setter 를 사용합니다.

  • 일반적으로 private 변수나 뭔가 바꾸려고 할때, getter 와 setter 를 사용하고 그 외의 경우에는 함수를 주로 사용하게 됩니다

void main() {
  // instance
  Staff jacob = Staff('Jacob', 30);
  jacob.sayName(); // 저는 Jacob 입니다

  print(jacob._name); // Jacob

  // getter 의 name 임
  print(jacob.name); // Jacob

  // setter 를 사용해서 값 변경
  jacob.name2 = 'Emma';
  print(jacob.name); // Emma
}

class Staff {
  String _name;
  int _age;

  // Constructor
  Staff(
    String name,
    int age,
  )   : this._name = name,
        this._age = age;

  void sayName() {
    print('저는 ${this._name} 입니다');
  }

  // getter 값을 가져와서 return 해줌
  get name {
    return this._name;
  }

  // setter 는 값을 바꿀때 사용
  // 한개의 parameter 를 사용해서 나중에 호출할때 값을 바꿀수 있다
  set name2(String name) {
    this._name = name;
  }
}

3.Class inheritance (상속)

  • 상속에는 부모 class 가 있고, 자식 class 가 있습니다. 부모는 여러개의 자식 class 가 있고, 자식 class 는 부모에 종속된 하나의 class 를 말합니다.

  • 부모의 class 는 자식의 class 를 상속받지 않습니다

  • 자식 class 에서 부모는 하나밖에 연결할 수 없습니다.

  • 자식 class 끼리는 서로 상속되지 않습니다

void main() {
  // instance
  Staff jacob = Staff('Jacob', 40);
  jacob.sayNmae(); // 저는 Jacob 입니다
  jacob.sayAge(); // 저의 나이는 40 입니다

  // 상속받은 People
  People john = People('John', 20);
  print(john.name); // 저는 John 입니다
}

class Staff {
  String name;
  int age;

  // constructure
  Staff(String name, int age)
      : this.name = name,
        this.age = age;

  void sayNmae() {
    print('저는 ${this.name} 입니다');
  }

  void sayAge() {
    print('저의 나이는 ${this.age} 입니다');
  }
}

// extends - 상속할때 사용, staff 의 있는 내용을 다 상속 받게 됩니다
// super 를 사용하게 되면 부모 class 의 constructure 를 가리키게 됨
class People extends Staff {
  // constructure
  People(
    String name,
    int age,
  ) : super(name: name, age: age);
}


class Hero {
  String name = 'Jacob';
  void run() {}
}

class SuperHero extends Hero {
  @override
  void run() {
    super.run(); // 부모의 run() 실행
    this.fly(); // 추가로 class 안에 fly 실행
  }

  void fly() {}
}

void main() {
  var hero = SuperHero();
  hero.run();
  hero.fly();
  print(hero.name); // Jacob
}

4.Method overriding

  • method 란? class 안의 함수를 가리킵니다

  • 만약 자식 class 에서 함수 class 를 override 하고 싶으면, @override 를 사용하고, 부모 class 에서 무언가 사용하고자 한다면 super 를 사용해서 가져와서 사용할 수 있습니다

void main() {
  Parnet parnet = Parnet(3);
  Child child = Child(3);

  print(parnet.calculate()); // 9
  // override 를 통해서 부모의 claculate() 함수를 바꿨음
  print(child.calculate()); // 9 에서 6으로 바꿈 또, result 로 super 를 사용해면 18 이 나옴
}

class Parnet {
  final int number;

  Parnet(
    int number,
  ) : this.number = number;

  // function = class 안에 있는 함수라서 Method 라고 함
  int calculate() {
    return this.number * this.number;
  }
}

class Child extends Parnet {
  Child(
    int number,
  ) : super(
          number,
        );

  // decorator
  // override 를 사용해서 자식 class 에서 기존에 있는 method 를 덮어쓰기 하는것
  @override
  int calculate() {
    // override 안에 super 를 사용해서 덮어 쓰기 한다음에 사용할 수 있음
    int result = super.calculate(); // 3 * 3 해서 9 가 나옴

    return result + result; // 9 + 9 = 18
  }
}

5.Class static keyword

  • 일반적으로 instance 에 귀속이 되지 않고 class 의 통채로 뭔가 귀속이 될때 사용되는것이 static keyword 입니다

  • static keyword 는 한번만 변경시키면 모든 keyword 에서 변경이 됩니다.

void main() {
  Staff jacob = Staff('Jacob');
  Staff emma = Staff('Emma');

  // static keyword 를 값을 넣는것
  Staff.building = 'A 동';

  jacob.printNameAndBuilding(); // 제 이름은 Jacob 입니다. A동 건물에서 근무하고 있습니다.
}

// Staff 안에는 직원 소속 건물 - 모든 직원들이 다 같은 건물 있을때
// 직원의 이름 - 이름은 사람마다 다 다름

class Staff {
  // 모두 똑같이 공통 사항일때는 static 을 사용해서 building 에 붙여서 사용
  static String building;
  String name;

  Staff(
    String name,
  ) : this.name = name;

  void printNameAndBuilding() {
    print('제 이름은 ${this.name} 입니다. $building 건물에서 근무하고 있습니다');
  }
}

6.super와 this 의 차이

void main() {
  Engineer member = Engineer(['Dart', 'Java', 'JS'], 'Jacob', 'A동');
  print(member.language); // [Dart, Java, JS]
  print(member.building); // A동
  print(member.name); // Jacob

  member
      .sayInfo(); // 저의 이름은 Jacob 입니다. 제가근무하는 빌딩은 A동 제가 할 수 있는 언어는 Dart,Java,JS 입니다
}

class Staff {
  final String building;
  final String name;

  Staff(
    String building,
    String name,
  )   : this.building = building,
        this.name = name;
}

// 사용할줄 언어를 리스트로 추가하기
class Engineer extends Staff {
  List<String> language;

  Engineer(
    List<String> language,
    String name,
    String building,
  )   : this.language = language,
        super(
          building,
          name,
        );

  void sayInfo() {
    // super.name 은 위에서 상속 받았으니까 super 라고 사용하긴 하는데, this.building 은 class 안에 사용했는데 똑같이 A동 을 출력 받았음 실제로 상속을 받을때는 모든것을 다 받기 때문에 class Engineer 에서 선언된 변수가 없더라도, 실제로 존재하는것처럼 보이게 됨
    // 자식에서 name을 선언을 해버리면 this 의 값이 우선되게 override 되기 때문에 그때는 class 안에 있는 값으로 this 로 불러와야 됨
    print(
        '저의 이름은 ${super.name} 입니다. 제가근무하는 빌딩은 ${this.building} 제가 할 수 있는 언어는 ${this.language.join(',')} 입니다');
  }
}

7.interface

  • class 가 꼭 선언해야되는 method 랑 변수들을 지정하게 해주는 기능을 함

  • interface를 사용하는 이유는 비슷한 성격을 가지고 있는 class 들은 꼭 이 변수와 함수를 가지고 있으면 좋겠다는 의미 라는 가정이 있을때 주로 사용됩니다

  • interface 같은 경우에는 무조건 그것을 상속해라는 것을 말하는것

  • 강제되는 성격에 무언가를 만들고 싶다고 하면 interface 를 사용면 됩니다

void main() {
  AGroup bts = AGroup('BTS');
  bts.sayName();
}

// 변수명과 함수에 이름만 지정을 한것임
class StaffInterface {
  final String name;

  StaffInterface(String name) : this.name = name;
  void sayName() {}
}

// implements 로 interface에 있는 것들을 AGroup 에서 반드시 선언을 해줘야 함
class AGroup implements StaffInterface {
  String name;

  AGroup(
    String name,
  ) : this.name = name;

  void sayName() {
    print('제 이름은 ${this.name} 입니다');
  }
}

class BGroup  implements StaffInterface{
  String name;

  AGroup(
    String name,
  ) : this.name = name;

  void sayName() {
    print('제 이름은 ${this.name} 입니다');
  }

}

8.cascade operator

  • method 를 작성할때 .. 을 2번 찍어서 사용하는 방식을 말함
void main() {
  Staff staff = Staff('Jacob', 'A');

  // staff 를 반복적으로 사용해서 호출해야 됨
  staff.sayName(); // 제 이름은 Jacob 입니다
  staff.sayGroup(); // 저는 A 소속입니다

  // 변수도 선언하지 않고 간단하게 .. cascade operator 를 사용해서 class 에 함수를 호출 할 수 있습니다
  // 주의 할 점은 맨 마지막에 ; 을 붙인다는 것임
  Staff('Emma', 'B')
    ..sayName() //제 이름은 Emma 입니다
    ..sayGroup(); // 저는 B 소속입니다
}

class Staff {
  String name;
  String group;

  Staff(
    String name,
    String group,
  )   : this.name = name,
        this.group = group;
  void sayName() {
    print('제 이름은 ${this.name} 입니다');
  }

  void sayGroup() {
    print('저는 ${this.group} 소속입니다');
  }
}

9.List 심화 (forEach, map, reduce, fold)

forEach (looping)

  • return 값을 안받고 그 안에서 도는것
void main() {
  List<String> staff = [
    'Jacob',
    'Emma',
    'John',
    'Mike',
  ];

  // forEach 람다식으로 JS 의 arrow function 처럼 사용
  staff.forEach((e) => print(e));
  // 각각의 값을 loop 돌면서 하나씩 출력함

  // 위와 똑같은 for loop
  for (String element in staff) {
    print(element);
  }
}

map (mapping)

  • forEach() 와 다르게 return 값을 받을 수 있는데, 각각 값에 새로운 값을 넣어줌

  • mapforEach 와 같이 처음부터 각각의 값으로 lopping 하게 됩니다. 근데 return 되는 값으로 각각 값을 변경 시킵니다. 새로운 list 를 return 해주게 됨

void main() {
  List<String> staff = [
    'Jacob',
    'Emma',
    'John',
    'Mike',
  ];

  // map
  final sayName = staff.map((e) => '제 이름은 $e 입니다');

  print(sayName);
  // (제 이름은 Jacob 입니다, 제 이름은 Emma 입니다, 제 이름은 John 입니다, 제 이름은 Mike 입니다)

  // 기존의 변수는 변경되지 않은것이 확인됨
  print(staff); // [Jacob, Emma, John, Mike]

  // 특이점은 map 의 return 값을 출력하게 되면 리스트의 형식이 [] => () 로 바껴있다. 왜냐면 map 은 iterable 을 return 해주기 때문 iterable 은 list 보다 부모 class 라고 보면 되는데 실제로는 list 형태로 많이 사용되기 때문에 .toList() 로 형변환 해주면 됨

  // [제 이름은 Jacob 입니다, 제 이름은 Emma 입니다, 제 이름은 John 입니다, 제 이름은 Mike 입니다]
  // print(sayName.toList());
}

reduce, fold

  • fold() 는 각각의 값들을 mapping 해가면서 그 값들을 이용해서 total 을 쌓아 가는 역활을 합니다.

  • reduce() 는 기본적으로 첫번째 값이 설정되어 있는 상태에서 fold() 와 비슷하지만, reduce 의 주의 사항은 들어오늘 값과 return 하는 값과 type 이 같아 야 한다

  • fold() 는 type 이 같지 않아도 된다

void main() {
  List<int> numbers = [0, 1, 2, 3, 4, 5];

  // fold(처음에 시작하는 값, (계속 누적되는 값, maping 되면서 하나씩 보이는 값) => 연산)
  int total =
      numbers.fold(0, (previousValue, element) => previousValue + element);

  print(total); // 15

  // reduce() 는 fold 와 비교 했을때, 시작하는 값을 넣지 않아도 됨 reduce는 기본 값으로 항상 첫번째 값이 들어가게 되어 있음 그래서 생략을 하는것임

  int total2 = numbers.reduce((value, element) => value + element);
  print(total2);

  // reduce() 가 type 이 같은때는 간단한데 fold 가 필요한경우는 type 이 다를때 주로 사용됨

  List<String> names = ['Jacob', 'Emma', 'John'];

  int total3 =
      names.fold(0, (previousValue, element) => previousValue + element.length);

  print(total3); // list 의 총 글자의 갯수를 int 형태로 return 받을 수 있다
}

10.Map 심화 (entries, asMap)

  • entries 를 사용해서 key, value 값을 전부 끌어다가 사용을 함

  • asMap() : 맵 형태 key : value 형태로 바꿔주는것 (index 번호: 실제 value 이런식으로 list 를 map 으로 바꿀 수 있음)

void main() {
  Map map = {
    'Apple': '사과',
    'Banana': '바나나',
    'Kiwi': '키위',
  };

  // iterable 값으로 return 됨
  print(map.keys); // (Apple, Banana, Kiwi)
  print(map.values); // (사과, 바나나, 키위)

  // 리스트로 바꾸기 - list 로 바꾸면 list 에 매소드를 다 사용할 수 있게 됨
  print(map.keys.toList()); // [Apple, Banana, Kiwi]
  print(map.values.toList()); // [사과, 바나나, 키위]

  // map 에서 mapping 하기 => entry

  // enrty 는 key 값과 value 값들을 다 가져 올 수 있음
  final newMap = map.entries.map((e) {
    final keys = e.key;
    final value = e.value;

    return '$keys 는 한글로 $value 입니다';
  });

  print(
      newMap); // (Apple 는 한글로 사과 입니다, Banana 는 한글로 바나나 입니다, Kiwi 는 한글로 키위 입니다)

  // entry 를 사용해서 forEach, reduce, fold 등을 다 사용할 수 있습니다.
  map.entries.forEach((element) {
    final key1 = element.key;
    final value1 = element.value;
    print('$key1 는 한글로 $value1 입니다');
  }); // Apple 는 한글로 사과 입니다
// Banana 는 한글로 바나나 입니다
// Kiwi 는 한글로 키위 입니다

  // asMap()
  List<int> numbers = [1, 2, 3, 4, 5, 6, 7];
  final newMap3 = numbers.asMap();
  print(newMap3); // {0: 1, 1: 2, 2: 3, 3: 4, 4: 5, 5: 6, 6: 7}

  // index를 가져 올수 있기 때문에 응용해서
  final newMap4 = numbers.asMap().entries.map((e) {
    final index = e.key;
    final value = e.value;

    return 'index 가 $index 일때 값은 $value 입니다';
  });
  print(newMap4);
  // (index 가 0 일때 값은 1 입니다, index 가 1 일때 값은 2 입니다, index 가 2 일때 값은 3 입니다, ..., index 가 5 일때 값은 6 입니다, index 가 6 일때 값은 7 입니다)
}

🔶 🔷 📌 🔑

Reference

Categories:

Updated:

Leave a comment