본문 바로가기
다트(Dart) 언어 강좌

상속과 다형성을 알아보자

by everythingdev 2024. 7. 25.
반응형

상속과 다형성 객체 지향 프로그래밍의 핵심 개념에 대해 알아보자

  • 플러터를 시작하기 전 다트(Dart) 언어의 개념에 대해 정리를 해보고자 합니다.
  • 다트(Dart) 언어 개념 정리 포스팅 후 플러터(Flutter) 개념 정리로 넘어갈 예정입니다.
  • 플러터(Flutter) 개념 정리 후 실습이 시작 된다고 보시면 될 것 같습니다.

소개

  • 다트(Dart)는 구글이 개발한 프로그래밍 언어로, 특히 Flutter 프레임워크와 함께 모바일 애플리케이션 개발에 널리 사용되고 있습니다.
  • 다트는 객체 지향 프로그래밍(OOP) 패러다임을 따르며, 이 중 상속과 다형성은 매우 중요한 개념입니다.
  • 이번 포스팅에서는 다트에서의 상속과 다형성에 대해 자세히 알아보고, 이를 효과적으로 활용하는 방법에 대해 설명 해보도록 하겠습니다.

다트에서의 상속

상속의 기본 개념

상속은 기존 클래스의 속성과 메서드를 새로운 클래스가 물려받는 것을 의미합니다. 다트에서는 extends 키워드를 사용하여 상속을 구현합니다. 상속을 통해 코드 재사용성을 높이고, 계층적인 클래스 구조를 만들 수 있습니다.

class Animal {
  void makeSound() {
    print('The animal makes a sound');
  }
}

class Dog extends Animal {
  @override
  void makeSound() {
    print('The dog barks');
  }
}
  • 이 예제에서 Dog 클래스는 Animal 클래스를 상속받아 makeSound 메서드를 오버라이드하고 있습니다.

상속의 장점

  • 코드 재사용 : 공통된 특성을 가진 여러 클래스를 만들 때, 중복 코드를 줄일 수 있습니다.
  • 계층 구조 : 객체 간의 관계를 명확하게 표현할 수 있습니다.
  • 유지보수 용이성: 공통 코드를 한 곳에서 관리할 수 있어 유지보수가 쉬워집니다.

다트의 단일 상속

다트는 단일 상속만을 지원합니다. 즉, 한 클래스는 오직 하나의 부모 클래스만을 가질 수 있습니다. 이는 다중 상속으로 인한 복잡성과 모호성을 피하기 위한 설계 결정입니다.

class A {}
class B {}
class C extends A {} // 가능
// class D extends A, B {} // 오류: 다중 상속 불가능

다트에서의 다형성

다형성의 기본 개념

다형성은 같은 인터페이스나 메서드가 다양한 방식으로 동작할 수 있게 하는 개념입니다. 다트에서는 메서드 오버라이딩과 인터페이스를 통해 다형성을 구현합니다.

메서드 오버라이딩

자식 클래스에서 부모 클래스의 메서드를 재정의하는 것을 메서드 오버라이딩이라고 합니다. 이를 통해 같은 메서드 이름으로 다양한 동작을 구현할 수 있습니다.

class Shape {
  double area() {
    return 0;
  }
}

class Circle extends Shape {
  double radius;

  Circle(this.radius);

  @override
  double area() {
    return 3.14 * radius * radius;
  }
}

class Rectangle extends Shape {
  double width;
  double height;

  Rectangle(this.width, this.height);

  @override
  double area() {
    return width * height;
  }
}

  • 이 예제에서 CircleRectangle 클래스는 각각 Shape 클래스를 상속받아 area 메서드를 오버라이드하고 있습니다.

인터페이스를 통한 다형성

다트에서는 별도의 interface 키워드 없이 클래스를 인터페이스로 사용할 수 있습니다. implements 키워드를 사용하여 인터페이스를 구현합니다.

abstract class Drawable {
  void draw();
}

class Circle implements Drawable {
  @override
  void draw() {
    print('Drawing a circle');
  }
}

class Square implements Drawable {
  @override
  void draw() {
    print('Drawing a square');
  }
}

void drawShape(Drawable shape) {
  shape.draw();
}

void main() {
  drawShape(Circle());
  drawShape(Square());
}
  • 이 예제에서 Drawable 인터페이스를 구현한 CircleSquare 클래스는 모두 draw 메서드를 가지고 있지만, 각각 다르게 동작합니다.

상속과 다형성의 활용

추상 클래스

다트에서 추상 클래스는 abstract 키워드를 사용하여 정의합니다. 추상 클래스는 직접 인스턴스화할 수 없으며, 상속을 통해 구체화된 클래스를 만들어야 합니다.

abstract class Vehicle {
  void move();
}

class Car extends Vehicle {
  @override
  void move() {
    print('The car drives on the road');
  }
}

class Boat extends Vehicle {
  @override
  void move() {
    print('The boat sails on the water');
  }
}
  • 추상 클래스를 사용하면 공통된 인터페이스를 정의하고, 구체적인 구현은 자식 클래스에 맡길 수 있습니다.

믹스인(Mixin)

다트는 다중 상속을 지원하지 않지만, 믹스인을 통해 여러 클래스의 기능을 조합할 수 있습니다. 믹스인은 with 키워드를 사용하여 클래스에 추가합니다.

mixin Flyable {
  void fly() {
    print('Flying');
  }
}

mixin Swimmable {
  void swim() {
    print('Swimming');
  }
}

class Duck extends Animal with Flyable, Swimmable {
  @override
  void makeSound() {
    print('Quack');
  }
}
  • 이 예제에서 Duck 클래스는 Animal을 상속받으면서 FlyableSwimmable 믹스인의 기능도 함께 가지게 됩니다.

결론

  • 다트에서의 상속과 다형성은 객체 지향 프로그래밍의 핵심 개념을 효과적으로 구현할 수 있게 해줍니다. 상속을 통해 코드 재사용성을 높이고, 다형성을 통해 유연하고 확장 가능한 코드를 작성할 수 있습니다. 추상 클래스와 믹스인과 같은 고급 기능을 활용하면 더욱 강력하고 유지보수가 용이한 애플리케이션을 개발할 수 있습니다.
  • 이러한 개념들을 잘 이해하고 적절히 활용한다면, 다트를 사용하여 더 효율적이고 구조화된 프로그래밍을 할 수 있을 것입니다. 특히 Flutter와 같은 프레임워크를 사용할 때, 이러한 객체 지향 프로그래밍의 특성을 잘 활용하면 더욱 강력하고 유지보수가 쉬운 애플리케이션을 개발할 수 있습니다.

맺음말

  • 이번 포스팅에서는 다트의 상속과 다형성에 대해 알아보았습니다.
  • 다음 포스팅에서는 다트의 추상 클래스와 인터페이스에 대해 알아보고자 합니다.
반응형