본문 바로가기
Dart

[Dart] 언어 기본기 - 클래스편

by 가드 2022. 12. 10.
728x90

Dart 클래스

클래스는 객체 지향 프로그래밍에서 특정 객체를 생성하기 위해 변수와 메서드를 정의하는 일종의 데이터의 집합체이다. 

 

테스트를 진행할 클래스 조건을 정해보자.

  • Book이라는 책 클래스를 선언
  • 책은 이름을 가지고 있다.
  • 책은 책 고유 번호를 가지고 있다.
  • 책이 판매되고 있는 서점 목록을 가지고 있다.
void main() {
  Book book = Book(); // new가 넣어도 되고 안넣어도 된다. 동일하다.
  book.bookName();
  book.bookNo();
  book.saleShops();
}


class Book {
  String name = '플루터'; 
  int no = 10;
  List<String> shops = ['교보문고', '영풍문고', '알라딘', '예스24'];  
  
  void bookName() {
    print('책의 이름은 ${this.name} 입니다.');
  }
  
  void bookNo() {
    print('책의 번호는 ${this.no} 입니다.');
  }
  
  void saleShops() {
    print(shops);
  }
}
  • Book class를 선언하고 책 이름을 가지는 String name, 책 고유번호를 가지는 int no, 책을 판매하는 서점을 가지는 List<String> shops 필드들을 정의하였다
  • Book class 안에 책의 이름을 출력하는 bookName(), 책의 고유번호를 출력하는 bookNo(), 책을 판매하는 서점을 출력해주는 saleShops() 함수를 가진다.
  • main() 함수에서 Book book = Book(); 코드로 Book class 인스턴스를 생성해주고 클래스 변수인 book을 이용하여 정보 출력해주는 함수들을 호출해주었다. (참고로 : Dart언어에서 new Book();과 Book();은 같다 new를 선언해도 되고 안 해도 무방하다.)
  • Class는 기본 Constructor(생성자)를 가지고 있다. main Book 클래스 생성했을 때 사용했던 Book()이다. 클래스 생성할 때 추가 정보를 넘겨주지 않고 기본정보로만 클래스를 생성한 것이다. 책은 다양한데 클래스 안에서 필드 정보를 가지고 있으면 책의 내용을 변경할 수 없다. 그래서 클래스는 Constructor로 추가 정보들을 받아서 생성해야 한다.

생성자(Constructor)를 이용하여 클래스 생성

void main() {
  Book book1 = Book('Dart', 10, ['교보문고', '영풍문고', '알라딘', '예스24']);
  book1.bookName(); // 책의 이름은 Dart 입니다.
  book1.bookNo(); // 책의 번호는 10 입니다.
  book1.saleShops(); // 책 판매점은 [교보문고, 영풍문고, 알라딘, 예스24] 입니다.
  
  Book book2 = Book('Flutter', 20, ['반디앤루니스', '인터파크']);
  book2.bookName(); // 책의 이름은 Flutter 입니다.
  book2.bookNo(); // 책의 번호는 20 입니다.
  book2.saleShops(); // 책 판매점은 [반디앤루니스, 인터파크] 입니다.
}


class Book {
  String name; 
  int no;
  List<String> shops;  
  
  Book(String name, int no, List<String> shops)
    : this.name = name, this.no = no, this.shops = shops;
  
  void bookName() {
    print('책의 이름은 ${this.name} 입니다.');
  }
  
  void bookNo() {
    print('책의 번호는 ${this.no} 입니다.');
  }
  
  void saleShops() {
    print('책 판매점은 ${this.shops} 입니다.');
  }
}
  • Book(String name, int no, List<String> shops) : namer, no, shops를 받을 수 있는 생성자를 정의하고 각 해당하는 변수에 대입을 시켜준다. this.name = name
  • Main() 함수에서 Book(name, no, shops)의 정보로 Book 클래스를 생성해주고 클래스 변수로 출력 함수들을 호출해 주었다. 예제로 book1, book2 클래스 생성 시 서로 다른 정보를 입력해주고 출력 함수들을 호출해주면 Book 클래스 하나로 서로 다른 정보를 가지고 다른 정보를 출력해주는 것을 확인할 수 있다.

생성자(Constructor)를  간결하게 작성하는 법

기존 생성자 코드
Book(String name, int no, List<String> shops)
    : this.name = name, this.no = no, this.shops = shops;
    
간결한 생성자 코드
Book(this.name, this.no, this.shops)
  • 생성자에서 변수 정보들을 받아서 대입시키는 코드보다 this.변수로 바로 정의해도 동일하기 때문에 생성자에 this로 클래스 변수로 바로 정의해 주는 것이 코드가 더 깔끔해진다.

네임드 파라미터로 생성자(Constructor)를 생성하는 법

of라는 이름을 가지는 생성자 추가
  Book.of(List values) :
    this.name = values[0], this.no = values[1], this.shops = values[2];
    
void main() {
  Book book = Book.of(['Flutter', 20, ['반디앤루니스', '인터파크']]);
 }
  • 클래스.생성자명(클래스 파라미터) 방식으로 정의가 가능하다. 위의 코드는 Book.of(List values)로 of로 Book 클래스를 생성할 수 있고 생성자 정보는 List로 받아서 클래스 정보를 세팅해준다.
  • main() 함수도 역시 Book.of(List)로 클래스를 생성하였다.
  • 네임드 파라미터는 어떠한 클래스 파라미터를 전달할 수 있다.

클래스 비교

void main() {
  Book book1 = Book('Dart', 10, ['교보문고', '영풍문고', '알라딘', '예스24']);
  Book book2 = Book('Dart', 10, ['교보문고', '영풍문고', '알라딘', '예스24']);
  print(book1 == book2); // false
}

book1과 book2의 데이터가 모두 동일하다면 클래스는 같다고 생각된다. 하지만 프로그래밍 언어는 두 개의 클래스는 다르다고 인식을 한다. 대부분의 언어들이 동일하다. dart에서는 클래스 앞에 const 키워드 선언 시에는 같은 클래스라고 판단하게 된다.

void main() {
  Book book1 = const Book('Dart', 10, ['교보문고', '영풍문고', '알라딘', '예스24']);
  Book book2 = const Book('Dart', 10, ['교보문고', '영풍문고', '알라딘', '예스24']);
  print(book1 == book2); // true
}
class Book {
  final String name; 
  final int no;
  final List<String> shops;  
  
  const Book(String name, int no, List<String> shops)
    : this.name = name, this.no = no, this.shops = shops;
}

const 사용 시 book1과 book2 같은 클래스가 된다. const 사용 조건은 생성자 앞에 const 키워드를 선언해야 하고 변수들은 final 키워드로 선언해야 한다.

클래스 Getter, Setter 사용

  • Getter : 변수 정보를 가져오는 함수
  • Setter : 변수를 저장하는 함수
void main() {
  Book book = Book('Dart', 10, ['교보문고', '영풍문고', '알라딘', '예스24']);
  print(book.firstShop); // 교보문고
  book.firstShop = '인터파크';
  print(book.firstShop); // 인터파크
}

class Book {
  String name;
  int no;
  List<String> shops;

  Book(String name, int no, List<String> shops)
      : this.name = name,
        this.no = no,
        this.shops = shops;
  // getter
  String get firstShop {
    return this.shops[0];
  }
  String getFirstShop() {
    return this.shops[0];
  }
  
  //setter
  set firstShop(String shop) {
    this.shops[0] = shop;
  }
  setFirstShop(String shop) {
    this.shops[0] = shop;
  }
}
  • getter는 get 키워드를 선언하는 방식과 함수명을 사용하는 방식 두 가지가 있다.
  • setter는 set 키워드를 선언하는 방식과 함수명을 상용하는 방식 두 가지가 있다.

두 가지 다 기능상 다른 점은 없다. 뉘앙스의 차이가 있다. 키워드 함수는 간단하게 가공할 때 사용하고 함수는 로직이 많이 들어가는 형태로 사용하게 된다. 그러나 어떠한 특정 상황에서 키워드를 사용해야 하고 어떠한 상황에서 함수를 사용해야 하고 없다고 생각해도 무방하다.

내 생각은 그냥 편한 거 사용해도 무방하다!!라는 입장이다.

300x250

'Dart' 카테고리의 다른 글

[Dart] 언어 기본기 - 오버라이드편  (0) 2022.12.12
[Dart] 언어 기본기 - 상속편  (0) 2022.12.11
[Dart] 언어 기본기 - Typedef편  (0) 2022.12.09
[Dart] 언어 기본기 - 함수편  (0) 2022.12.08
[Dart] 언어 기본기 - Enum편  (0) 2022.12.07

댓글