subindev 님의 블로그

[Flutter] #3 Dart 기본 문법 클래스와 인스턴스 본문

앱개발/Flutter

[Flutter] #3 Dart 기본 문법 클래스와 인스턴스

subindev 2025. 1. 3. 18:43

Dart 프로그래밍 기초

 

1. 클래스와 인스턴스 


클래스란?

클래스란 객체를 정의하는 설계도라고 할 수 있습니다. 객체가 가지게 될 속성과 행동을 정의합니다. 객체는 그 설계도를 바탕으로 실제로 메모리에 만들어진 인스턴스입니다.

  • 속성 (Attributes/Fields): 클래스가 정의하는 객체의 상태를 나타내는 변수들입니다. 예를 들어, 강아지 클래스를 만들 때 강아지의 이름, 나이, 색상 등을 속성으로 정의할 수 있습니다.
  • 행동 (Methods): 클래스가 정의하는 객체의 동작을 나타내는 함수들입니다. 예를 들어, 강아지가 짖거나, 물을 마시는 등의 행동을 메소드로 정의할 수 있습니다.

 객체 지향 프로그래밍(OOP) 이란?  

객체와 객체간에 관계를 형성하고, 그 상호작용을 통해 애플리케이션을 설계, 구현하는 프로그래밍 패러다임 중 하나 입니다. OOP 에 주요 목적은 복잡한 문제를 더 작은 객체로 나누는 것에 있습니다.

 

시나리오 코드 1 - 클래스 만들어 보기

void main() {
  // Dog d1 = new Dog(); // 인스턴스화 되었다.
  Dog d1 = Dog(); // 인스턴스화 되었다. new 키어드를 대 부분 생략한다.
  print('강아지 이름 ${d1.name}');
  print('강아지 나이 ${d1.age}');
  print('강아지 색상 ${d1.color}');
  print('강아지 현재 갈증 지수 ${d1.thirsty}');

  d1.thirsty = 50;
  print('강아지 현재 갈증 지수 ${d1.thirsty}');
} // end of main

// 자바 ---> .하나의 자바 파일에 public class 를 두개 선언할 수 있나요? No

class Dog {
  // 변수에 선언과 동시에 초기화(값을 넣다)
  String name = '토토';
  int age = 5;
  String color = '블랙';
  int thirsty = 100;
}

 

 

시나리오 2 - 메소드 만들어 보기

// 코드의 진입점
void main() {
  // Dog d1 = new Dog(); // 인스턴스화 되었다.
  Dog d1 = Dog(); // 인스턴스화 되었다. new 키어드를 대 부분 생략한다.
  print('강아지 이름 ${d1.name}');
  print('강아지 나이 ${d1.age}');
  print('강아지 색상 ${d1.color}');
  print('강아지 현재 갈증 지수 ${d1.thirsty}');
  // d1.thirsty = 50;
  d1.drinkWater();
  d1.drinkWater();
  d1.drinkWater();
  d1.drinkWater();
  d1.drinkWater();
  print('강아지 현재 갈증 지수 ${d1.thirsty}');
} // end of main

// 틈새질문 Q1) 자바 - 하나의 자바 파일(.java)에 public class 를 두개 선언할 수 있나요? NO

class Dog {
  // 변수에 선언과 동시에 초기화(값을 넣다)
  String name = '토토';
  int age = 5;
  String color = '블랙';
  int thirsty = 100;

  // 2. 물을 마실 때 마다 갈증 지수가 10씩 내려간다.
  void drinkWater() {
    thirsty = thirsty - 10;
  }
}

 

 

시나리오 3 - 협력하기(상호작용)

// 코드의 진입점
void main() {
  Dog d1 = Dog();
  Water w1 = Water();
  Water w2 = Water();
  d1.drinkWater(w2);
  print(w2.liter);
} // end of main

// 자바 ---> .하나의 자바 파일에 public class 를 두개 선언할 수 있나요?

class Dog {
  // 변수에 선언과 동시에 초기화(값을 넣다)
  String name = '토토';
  int age = 5;
  String color = '블랙';
  int thirsty = 100;

  // 2. 물을 마실 때 마다 갈증 지수가 10씩 내려간다.
  void drinkWater(Water water) {
    thirsty = thirsty - 10;
    water.drink();
  }
}

class Water {
  double liter = 2.0; // 물 2리터

  void drink() {
    // liter = liter - 0.1;
    liter -= 0.1;
  }
}

 

2. 생성자 (Constructor)


생성자란 ?  클래스명( );

클래스의 인스턴스를 초기화하는 특별한 메서드입니다. 클래스가 인스턴스화 될 때 호출되며, 객체의 속성 값들을 설정하고 객체의 상태를 정의하는 역할을 합니다.

생성자는 일반 메서드와 달리 클래스 이름과 동일한 이름을 가지며, 객체가 생성될 때 자동으로 호출됩니다.

생성자의 주요 특징

  1. 클래스 이름과 동일한 이름을 가집니다.
  2. 반환 타입이 없다 (즉, void 또는 다른 타입을 지정하지 않습니다).
  3. 객체가 생성될 때 자동으로 호출됩니다.
  4. 매개변수를 통해 객체를 초기화할 수 있습니다.

기본 생성자

  • 기본 생성자는 매개변수가 없는 생성자입니다. Dart에서는 명시적으로 정의하지 않으면 자동으로 제공됩니다.
class Car {
  String model = "Unknown"; 
  int year = 0;
  
  // String model; - 만약 이렇게 적혔다면
  // int year;
  
  // 기본 생성자 (Dart가 자동으로 제공)
}

void main() {
  var myCar = Car();  // 기본 생성자 호출
  print(myCar.model);  // "Unknown"
  print(myCar.year);   // 0
  
  // print(myCar.model);  // null - 이렇게 될 것 이다.
  // print(myCar.year);   // null
}

 

사용자 정의 생성자

  • 사용자 정의 생성자는 클래스의 인스턴스를 생성할 때, 더 구체적인 초기화 작업을 할 수 있게 해주는 생성자입니다.

시나리오 코드 4 - 생성자 만들기와 생성자 오버로딩은 없다.

// 코드의 진입점
void main() {
  // 생성자
} // end of main

// dart 라는 언어는 기본적으로 null 값을 허용 하지 않는다.
class Dog {
  String name;
  int age;
  String color;
  int thirsty;

  // Dog(this.name, this.age, this.color, this.thirsty) {}
  Dog(this.name, this.age, this.color, this.thirsty); // 생성자 구현 부분 생략 가능
  // Dog(this.name, this.age); 이거 안됨 --> dart 에서는 생성자 오버로딩이 없다.
}

class Water {
  double liter = 2.0; // 물 2리터

  void drink() {
    // liter = liter - 0.1;
    liter -= 0.1;
  }
}

 

3. 선택적 명명 매개변수 ( {  } )

 

1. 선택적 위치 매개변수 (Optional Positional Parameters)

  • 선택적 위치 매개변수는 [] 대괄호로 감싸서 정의합니다.
  • 매개변수를 생략할 수 있으며, 생략된 매개변수는 null이 기본값이 됩니다.
  • 기본값을 지정하려면 = 연산자를 사용합니다.

2. 선택적 명명 매개변수 (Optional Named Paramters)

  • 선택적 명명 매개변수는 {} 중괄호로 감싸서 정의합니다.
  • 함수 호출 시 매개변수 이름을 지정해서 전달합니다.
  • 기본값을 지정하거나 required 키워드를 사용하여 특정 매개변수를 필수로 설정할 수 있습니다.

생성자도 또한 메서드이므로 선택적 명명 매개변수를 이용할 수 있습니다. 선택적 명명 변수를 이용하면 required 키워드를 사용하여 특정 매개변수를 필수로 설정할 수 있습니다. 이러한 방식은 Java에서 오버로딩으로 처리하던 다양한 생성자를 선택적 명명 매개변수로 간단하게 대체할 수 있게 합니다. 즉 Dart 에서는 오버로딩이 필요 없습니다.

// 코드의 진입점
void main() {
  // 생성자
  Dog(name: '토토', age: 5);
} // end of main


// dart 라는 언어는 기본적으로 null 값을 허용 하지 않는다.
class Dog {
  String name;
  int age;
  // String 옵셔널 타입은 null 허용 시키는 타입이다.
  String? color;
  int? thirsty;

  // {} 붙이면 선택적 명명 매개 변수
  Dog(
      {required this.name,
      required this.age,
      this.color = '블랙',
      this.thirsty = 100});
}

class Water {
  double liter = 2.0; // 물 2리터

  void drink() {
    // liter = liter - 0.1;
    liter -= 0.1;
  }
}

 

  시나리오 코드 6 - 복습

// 코드의 진입점
void main() {
  // 오버로딩 보다 더 강력한 선택적 매개 변수가 있기 때문에 dart 는 오버로딩이 없다.
  Person(name: '홍길동');
} // end of main

class Person {
  String name;
  int? money;

  Person({required this.name}) {}
}

 

3. 캐드케이스 연산자 (cascade)  ' ... '


캐드케이스 연산자는 Dart에서 동일한 객체에 대해 여러 메서드 호출이나 속성 설정을 연속적으로 수행할 때 사용하는 유용한 연산자입니다. 이 연산자를 사용하면 코드의 가독성을 높이고, 중복된 객체 참조를 줄일 수 있습니다.

객체 초기화 시 여러 속성을 설정해야할 때, 동일 객체에서 여러 메서드를 호출할 때 주로 사용됩니다. 'Buidler pattern'과 유사한 작업에서 사용할 수 있습니다.

class Person {
  String? name;
  int money = 0;

  void setName(String newName) {
    this.name = newName;
  }

  void addMoney(int amount) {
    // this.money = this.money = amount;
    this.money += amount;
  }
}

void main() {
  var p1 = Person()
    ..setName('홍길동')
    ..addMoney(5000)
    ..money += 2000;
  print(p1.name);
  print(p1.money);
} // end of main