본문 바로가기
Flutter for Beginners

Dart: Generics, Static, Cascade Operator

by Andrew's Akashic Records 2025. 2. 25.
728x90

Dart

제네릭(Generics), 스태틱(Static), 캐스케이드 연산자(Cascade Operator)

Dart의 객체지향 프로그래밍(OOP)에서는 제네릭(Generic), 정적 변수/메서드(Static), 캐스케이드 연산자(Cascade Operator) 를 사용하여 유연하고, 효율적인 코드 작성이 가능합니다.

1. 제네릭 (Generics)

제네릭(Generic)은 데이터 타입을 일반화하여 다양한 타입의 객체를 처리할 수 있도록 하는 기능입니다.
Dart에서는 리스트(List), 맵(Map), 클래스, 함수에서 제네릭을 활용할 수 있습니다.

1.1 제네릭을 사용하지 않은 경우

void main() {
  List names = ["Alice", "Bob", "Charlie"];
  names.add(100); // 의도하지 않은 타입 추가 가능

  print(names); // ["Alice", "Bob", "Charlie", 100]
}
  • 문제점: List가 String만 저장해야 하는데 int도 추가됨 → 타입 안정성이 깨짐

1.2. 제네릭을 사용한 리스트

void main() {
  List<String> names = ["Alice", "Bob", "Charlie"];

  // names.add(100); // 오류 발생 (String 타입만 허용)

  print(names); // ["Alice", "Bob", "Charlie"]
}
  • 제네릭을 사용하면 타입 안정성을 유지할 수 있음

1.3. 제네릭을 사용하는 클래스

class Box<T> {
  T value;

  Box(this.value);

  void show() {
    print("Value: $value");
  }
}

void main() {
  Box<int> intBox = Box(123);
  intBox.show(); // Value: 123

  Box<String> strBox = Box("Hello");
  strBox.show(); // Value: Hello
}
  • T를 사용하여 다양한 타입을 처리할 수 있는 유연한 클래스를 만들 수 있음

1.4. 제네릭을 사용하는 함수

T getFirst<T>(List<T> items) {
  return items.first;
}

void main() {
  print(getFirst<int>([1, 2, 3])); // 1
  print(getFirst<String>(["A", "B", "C"])); // A
}
  • 제네릭 함수는 여러 타입의 데이터를 처리할 때 유용함

2. 스태틱 (Static)

  • static 키워드를 사용하면 클래스의 인스턴스가 아닌 클래스 자체에 속하는 변수와 메서드를 정의할 수 있습니다.
  • 모든 객체가 공유하는 값이 필요할 때 사용됩니다.

2.1. 스태틱 변수

class MathUtils {
  static const double pi = 3.1415; // 모든 객체가 공유하는 상수
}

void main() {
  print(MathUtils.pi); // 3.1415
}
  • static 변수는 객체를 생성하지 않고도 접근 가능

2.2. 스태틱 메서드

class MathUtils {
  static double circleArea(double radius) {
    return pi * radius * radius;
  }

  static const double pi = 3.1415;
}

void main() {
  print(MathUtils.circleArea(5)); // 78.5375
}
  • 객체를 생성하지 않고 MathUtils.circleArea(5) 형태로 바로 사용 가능

2.3. 스태틱 변수와 인스턴스 변수 비교

class Counter {
  static int staticCount = 0; // 모든 객체가 공유하는 변수
  int instanceCount = 0; // 각 객체별 개별 변수

  void increment() {
    staticCount++;
    instanceCount++;
  }
}

void main() {
  Counter c1 = Counter();
  Counter c2 = Counter();

  c1.increment();
  print("c1 - staticCount: ${Counter.staticCount}, instanceCount: ${c1.instanceCount}"); // 1, 1

  c2.increment();
  print("c2 - staticCount: ${Counter.staticCount}, instanceCount: ${c2.instanceCount}"); // 2, 1
}
  • staticCount는 모든 객체에서 공유되지만, instanceCount는 각 객체별로 따로 유지됨

3. 캐스케이드 연산자 (Cascade Operator) ..

  • 객체를 여러 번 호출할 때, 매번 객체 변수를 반복적으로 사용하지 않도록 하는 문법
  • . 대신 ..을 사용하여 한 줄로 여러 메서드를 호출할 수 있음

3.1. 캐스케이드 연산자 사용 전

class Person {
  String name = "";
  int age = 0;

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

  void setAge(int age) {
    this.age = age;
  }

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

void main() {
  Person p = Person();
  p.setName("Alice");
  p.setAge(25);
  p.showInfo();
}
  • 객체의 여러 메서드를 호출할 때 매번 객체 변수를 반복적으로 사용해야 함

3.2. 캐스케이드 연산자 사용

void main() {
  Person p = Person()
    ..setName("Alice")
    ..setAge(25)
    ..showInfo();
}
이름: Alice, 나이: 25
  • 객체 변수를 반복하지 않고 한 줄로 여러 메서드를 호출 가능

3.3. 캐스케이드 연산자로 속성 변경

class Car {
  String brand = "";
  int year = 0;

  void showInfo() {
    print("브랜드: $brand, 연식: $year");
  }
}

void main() {
  Car myCar = Car()
    ..brand = "Tesla"
    ..year = 2023
    ..showInfo();
}
브랜드: Tesla, 연식: 2023
  • 속성과 메서드를 조합하여 간결한 코드 작성 가능

4. 제네릭, 스태틱, 캐스케이드 연산자 요약

개념 설명 예제
제네릭 (Generics) 여러 타입을 처리할 수 있도록 일반화 class Box<T> { T value; }
스태틱 (Static) 클래스 자체에 속하는 변수/메서드 static int count;
캐스케이드 연산자 (..) 객체를 반복적으로 호출할 때 간결한 코드 제공 object..method()..method();
  • 제네릭(Generic) → 유연한 코드 작성 가능
  • 스태틱(Static) → 클래스 수준 변수와 메서드 사용 가능
  • 캐스케이드 연산자(..) → 객체 조작을 간결하게 표현 가능

 

728x90