Menu
Coddy logo textTech

추상 메서드

Coddy Dart 여정의 객체 지향 프로그래밍 섹션에 포함된 레슨 — 110개 중 44번째.

추상 메서드(abstract method)는 본문이 없는 추상 클래스(abstract class) 내부에 선언된 메서드입니다. 이는 메서드 시그니처를 정의하지만 구현은 각 하위 클래스(subclass)에 맡깁니다. 추상 클래스를 상속받는 모든 클래스는 모든 추상 메서드를 반드시 오버라이드(override)해야 하며, 그렇지 않으면 해당 클래스도 추상 클래스가 됩니다.

abstract class Animal {
  // 추상 메서드 - 본문이 없으며, 하위 클래스에서 반드시 구현해야 함
  String makeSound();

  // 구체적인 메서드 - 본문이 있으며, 모든 하위 클래스에서 공유됨
  void breathe() {
    print('Breathing...');
  }
}

class Dog extends Animal {
  @override
  String makeSound() {
    return 'Woof!';  // 반드시 구현을 제공해야 함
  }
}

class Cat extends Animal {
  @override
  String makeSound() {
    return 'Meow!';  // 다른 구현, 동일한 시그니처
  }
}

만약 서브클래스가 추상 메서드를 구현하는 것을 잊는다면, Dart는 컴파일 에러를 발생시킵니다. 이것이 바로 핵심입니다 - 추상 메서드는 계약을 강제합니다. 모든 서브클래스는 해당 메서드를 갖는 것이 보장되므로, 추상 타입의 어떤 인스턴스에서도 안전하게 그 메서드를 호출할 수 있습니다.

// 추상 타입을 변수 타입으로 사용할 수 있습니다
Animal a = Dog();
print(a.makeSound());  // 멍멍!

Animal b = Cat();
print(b.makeSound());  // 야옹!

추상 메서드는 추상 클래스 내의 구체 메서드(concrete methods)와 다릅니다. 구체 메서드는 본문(body)을 가지며 있는 그대로 상속됩니다. 반면 추상 메서드는 본문이 없으며 반드시 오버라이드(재정의)되어야 합니다.

동일한 추상 클래스 내에서 두 가지를 혼합하여 일부 동작은 공유하면서, 다른 동작에 대해서는 서브클래스가 직접 정의하도록 강제할 수 있습니다.

기능추상 메서드구체 메서드
본문(body) 유무아니요
오버라이딩 필수 여부아니요
목적계약 강제동작 공유
선언 위치추상 클래스 전용모든 클래스
challenge icon

챌린지

쉬움

추상 메서드가 실제로 어떻게 작동하는지 보여주는 도형 계산기를 만들어 보겠습니다. 각 도형이 서로 다르게 구현해야 하는 추상 메서드를 가진 추상 클래스를 정의한 다음, 공통 인터페이스를 통해 해당 도형들을 사용해 볼 것입니다.

코드는 다음 네 개의 파일로 구성됩니다:

  • shape.dart: final 필드인 color (String)와 이를 초기화하는 생성자를 가진 추상 클래스 Shape를 정의합니다. 두 개의 추상 메서드 double area()double perimeter()를 선언하세요. 또한 A [color] shape with area: [area] and perimeter: [perimeter]를 출력하는 구체 메서드 describe()를 추가하세요. area()perimeter()는 추상 메서드이므로 각 서브클래스에서 자체적인 계산 방식을 제공하겠지만, describe()는 오버라이드 없이 모든 서브클래스에서 작동합니다.
  • circle.dart: Shape를 상속받는 Circle 클래스를 생성합니다. final 필드인 radius (double)를 가집니다. 생성자는 colorradius를 인자로 받아 colorsuper로 전달합니다. area()3.14 * radius * radius를 반환하도록 구현하고, perimeter()2 * 3.14 * radius를 반환하도록 구현하세요.
  • rectangle.dart: Shape를 상속받는 Rectangle 클래스를 생성합니다. final 필드인 widthheight (둘 다 double)를 가집니다. 생성자는 color, width, height를 인자로 받아 colorsuper로 전달합니다. area()width * height를 반환하도록 구현하고, perimeter()2 * (width + height)를 반환하도록 구현하세요.
  • main.dart: 모든 파일을 임포트합니다. 색상이 'red'이고 반지름이 5.0Circle과, 색상이 'blue'이고 너비가 4.0, 높이가 6.0Rectangle을 생성합니다. 각 도형에 대해 describe()를 호출하세요. 그런 다음 두 도형을 모두 포함하는 List<Shape>를 생성하고, 리스트를 반복문으로 돌면서 각 도형의 Area: [area]를 출력하세요.

예상 출력 결과:

A red shape with area: 78.5 and perimeter: 31.400000000000002
A blue shape with area: 24.0 and perimeter: 20.0
Area: 78.5
Area: 24.0

치트 시트

추상 메서드는 본문 없이 추상 클래스에서 선언된 메서드입니다. 하위 클래스는 자체적인 구현을 제공하기 위해 이를 반드시 오버라이드해야 합니다.

abstract class Animal {
  // 추상 메서드 - 본문 없음
  String makeSound();

  // 구체 메서드 - 본문 있음
  void breathe() {
    print('Breathing...');
  }
}

하위 클래스는 모든 추상 메서드를 구현해야 합니다:

class Dog extends Animal {
  @override
  String makeSound() {
    return 'Woof!';
  }
}

class Cat extends Animal {
  @override
  String makeSound() {
    return 'Meow!';
  }
}

추상 타입을 변수 타입으로 사용할 수 있습니다:

Animal a = Dog();
print(a.makeSound());  // Woof!

Animal b = Cat();
print(b.makeSound());  // Meow!
특징추상 메서드구체 메서드
본문 유무아니요
오버라이드 필수 여부아니요
목적계약 강제동작 공유
위치추상 클래스 전용모든 클래스

직접 해보기

import 'shape.dart';
import 'circle.dart';
import 'rectangle.dart';

void main() {
  // TODO: color가 'red'이고 radius가 5.0인 Circle을 생성하세요.

  // TODO: color가 'blue'이고 width가 4.0, height가 6.0인 Rectangle을 생성하세요.

  // TODO: circle에 대해 describe()를 호출하세요.

  // TODO: rectangle에 대해 describe()를 호출하세요.

  // TODO: 두 도형을 포함하는 List<Shape>를 생성하세요.

  // TODO: 리스트를 반복문으로 돌며 각 도형에 대해 "Area: [area]"를 출력하세요.
}
quiz icon실력 점검

이 레슨에는 짧은 퀴즈가 포함되어 있습니다. 레슨을 시작해 문제를 풀고 진행 상황을 기록하세요.

객체 지향 프로그래밍의 모든 레슨