티스토리 뷰

반응형

📌 Dart의 클래스 및 객체 지향 프로그래밍 (OOP) 개념과 문법 완벽 정리

Dart는 객체 지향 프로그래밍(OOP, Object-Oriented Programming)을 기반으로 하는 언어입니다.
Flutter 개발에서 클래스(Class)와 객체(Object)를 활용하는 것은 필수적인 개념이므로, 이번 글에서는 클래스 정의, 생성자, 상속, 인터페이스, Getter/Setter, 추상 클래스 등의 개념을 자세히 다루겠습니다.


🔹 1. 클래스(Class)와 객체(Object)

🔸 1️⃣ 클래스(Class) 정의 및 객체 생성

Dart에서 클래스는 객체를 생성하는 템플릿(설계도) 역할을 합니다.
클래스를 정의하고, 해당 클래스를 이용해 객체를 생성하는 기본 문법을 살펴보겠습니다.

class Person {
  String name = "홍길동";  // 속성 (멤버 변수)
  int age = 25;

  void sayHello() {  // 메서드 (함수)
    print("안녕하세요, 저는 $name입니다.");
  }
}

void main() {
  var person1 = Person();  // 객체 생성
  person1.sayHello();  // 안녕하세요, 저는 홍길동입니다.
}

출력:

안녕하세요, 저는 홍길동입니다.
  • class Person {} : 클래스를 정의합니다.
  • name, age : 멤버 변수 (속성)
  • sayHello() : 메서드 (함수)
  • var person1 = Person(); : Person 클래스를 이용해 객체를 생성

  • 클래스는 대문자로 시작하는 UpperCamelCase 네이밍 규칙을 따릅니다.
  • 객체를 생성할 때 new 키워드는 생략 가능합니다.
    var person1 = Person();  // 가능
    var person2 = new Person();  // 가능하지만 Dart 2.0 이후 권장하지 않음
    

🔹 2. 생성자 (Constructor)

객체를 만들 때 자동으로 호출되는 특별한 함수를 **생성자(Constructor)**라고 합니다.

🔸 1️⃣ 기본 생성자

class Person {
  String name;
  int age;

  // 기본 생성자
  Person(String name, int age) {
    this.name = name;
    this.age = age;
  }

  void introduce() {
    print("이름: $name, 나이: $age");
  }
}

void main() {
  var person = Person("철수", 30);
  person.introduce(); // 이름: 철수, 나이: 30
}
  • 생성자는 클래스 이름과 동일한 메서드이며, 객체가 생성될 때 자동 실행됩니다.
  • this.name = name; : this는 현재 객체를 가리키는 키워드입니다.

🔸 2️⃣ 생성자에서 this 키워드 생략하기 (간결한 표현)

class Person {
  String name;
  int age;

  // 간단한 생성자
  Person(this.name, this.age);

  void introduce() {
    print("이름: $name, 나이: $age");
  }
}

void main() {
  var person = Person("영희", 25);
  person.introduce(); // 이름: 영희, 나이: 25
}
  • this.name = name; 대신 this.name 형태로 선언하면 코드가 간결해집니다.

🔸 3️⃣ Named Constructor (이름 있는 생성자)

class Person {
  String name;
  int age;

  Person(this.name, this.age); // 기본 생성자

  // Named Constructor (이름 있는 생성자)
  Person.named({required this.name, required this.age});
}

void main() {
  var person = Person.named(name: "민수", age: 28);
  print("이름: ${person.name}, 나이: ${person.age}"); // 이름: 민수, 나이: 28
}
  • Person.named()처럼 여러 개의 생성자를 정의할 수 있음
  • required를 사용하면 반드시 값을 전달해야 하는 필드를 지정할 수 있음

🔹 3. Getter & Setter

Dart에서는 클래스의 멤버 변수를 직접 접근하지 않고 getter와 setter를 통해 값을 가져오거나 변경하는 것이 일반적입니다.

class Person {
  String _name; // private 변수 (앞에 _ 사용)
  
  Person(this._name);

  // Getter (값 읽기)
  String get name => _name;

  // Setter (값 변경)
  set name(String newName) {
    if (newName.length > 1) {
      _name = newName;
    } else {
      print("이름은 한 글자 이상이어야 합니다.");
    }
  }
}

void main() {
  var person = Person("철수");
  print(person.name);  // 철수

  person.name = "영희";
  print(person.name);  // 영희

  person.name = "A";  // 이름은 한 글자 이상이어야 합니다.
}
  • _name처럼 변수 앞에 _를 붙이면 **private 변수(외부에서 접근 불가)**가 됩니다.
  • get 키워드를 사용해 값을 읽을 수 있습니다.
  • set 키워드를 사용해 값을 변경할 때 조건을 추가할 수 있습니다.

🔹 4. 클래스 상속 (Inheritance)

Dart는 extends 키워드를 사용하여 **상속(Inheritance)**을 구현합니다.

class Animal {
  String name;

  Animal(this.name);

  void makeSound() {
    print("소리를 냅니다.");
  }
}

class Dog extends Animal {
  Dog(String name) : super(name);

  void bark() {
    print("$name: 멍멍!");
  }
}

void main() {
  var myDog = Dog("바둑이");
  myDog.makeSound(); // 소리를 냅니다.
  myDog.bark(); // 바둑이: 멍멍!
}
  • class Dog extends Animal : Animal 클래스를 상속받는 Dog 클래스
  • super(name) : 부모 클래스의 생성자를 호출하여 name을 초기화

🔹 5. 추상 클래스 (Abstract Class)

추상 클래스는 직접 객체를 생성할 수 없고, 반드시 상속받아 사용해야 하는 클래스입니다.

abstract class Vehicle {
  void move();  // 구현이 없는 메서드 (추상 메서드)
}

class Car extends Vehicle {
  @override
  void move() {
    print("자동차가 달립니다.");
  }
}

void main() {
  var myCar = Car();
  myCar.move(); // 자동차가 달립니다.
}
  • abstract 키워드를 사용하여 추상 클래스를 정의
  • move()는 구현이 없는 추상 메서드이므로, 반드시 하위 클래스에서 오버라이딩해야 함

🛠 정리

개념 설명

클래스 class ClassName {}
객체 생성 var obj = ClassName();
생성자 ClassName(this.name, this.age);
Named 생성자 ClassName.named({required this.name});
Getter & Setter String get name => _name;
상속 class Child extends Parent {}
추상 클래스 abstract class ClassName {}

🔥 Dart 클래스 활용 꿀팁

  1. 변수는 _를 사용해 private으로 설정하여 직접 접근을 막고, getter/setter로 관리.
  2. Named Constructor를 활용하면 객체 생성 시 다양한 초기화 옵션을 제공 가능.
  3. 상속과 super 키워드를 활용하여 코드 중복을 줄이고 유지보수성을 높일 수 있음.
  4. 추상 클래스를 사용하면 공통 인터페이스를 정의하고 확장성을 높일 수 있음.

 

반응형