플러터 강좌: 9.1 상속이란?

프로그래밍의 핵심 개념 중 하나인 상속은 객체 지향 프로그래밍의 가장 중요한 특징 중 하나로,
플러터에서도 객체 지향 프로그래밍의 원칙을 따르고 있습니다.
본 강좌에서는 플러터에서의 상속 개념, 사용 방법, 그리고 실전 예제를 통해
상속을 깊이 이해할 수 있도록 설명하겠습니다.

1. 상속의 정의

상속(Inheritance)은 기존 클래스(부모 클래스 또는 슈퍼 클래스)의 속성과
메서드를 새로운 클래스(자식 클래스 또는 서브 클래스)가
물려받는 것을 의미합니다. 이를 통해 코드 재사용을 극대화하고,
클래스 간의 관계를 쉽게 표현할 수 있습니다.

2. 상속의 필요성

상속은 다음과 같은 이유로 필요합니다:

  • 코드 재사용: 이미 작성한 코드가 새로운 클래스에서 재사용됨으로써,
    코드의 중복을 줄이고, 유지 보수를 용이하게 합니다.
  • 유지 보수: 부모 클래스에 변경이나 버그 수정이 일어날 경우,
    이를 상속받은 모든 자식 클래스에서 자동으로 적용됩니다.
  • 계층 구조: 관련 클래스 간의 계층 구조를 만들어
    프로그램의 가독성을 높이는데 기여합니다.

3. 플러터에서의 상속 사용법

플러터에서는 Dart 언어를 기반으로 하기 때문에, Dart의 상속 구현 방식을 따릅니다.
Dart에서 클래스를 상속받으려면 `extends` 키워드를 사용합니다.
기본적인 문법은 다음과 같습니다.

class Parent {
    void show() {
        print("이것은 부모 클래스의 메서드입니다.");
    }
}

class Child extends Parent {
    void display() {
        print("이것은 자식 클래스의 메서드입니다.");
    }
}

위의 예제에서 `Child` 클래스는 `Parent` 클래스를 상속받아
`show()` 메서드를 사용할 수 있으며, 또한 `Child` 클래스만의
`display()` 메서드를 정의할 수 있습니다.

4. 메서드 오버라이딩

상속을 통해 부모 클래스의 메서드를 자식 클래스에서 재정의하는
과정을 메서드 오버라이딩(Method Overriding)이라고 합니다.
이를 통해 자식 클래스는 부모 클래스의 메서드를
자신만의 방식으로 구현할 수 있습니다.

class Parent {
    void show() {
        print("부모 클래스의 show()");
    }
}

class Child extends Parent {
    @override
    void show() {
        print("자식 클래스의 show()");
    }
}

`@override` 키워드를 사용하면 부모 클래스에서 상속받아
오버라이드할 메서드를 명시적으로 표시할 수 있으며,
이를 통해 코드의 명확성을 높일 수 있습니다.

5. 다중 상속과 믹스인

Dart는 다중 상속을 지원하지 않지만, 믹스인을 사용하여
여러 클래스를 결합할 수 있습니다. 믹스인은
클래스가 아닌 다른 클래스를 통해 코드 재사용을 가능하게 하는
방법입니다. 믹스인을 정의하려면 `mixins` 키워드를
사용할 수 있습니다.

mixin MixinA {
    void methodA() {
        print("믹스인 A의 메서드");
    }
}

class Base {}

class Child extends Base with MixinA {
    void methodB() {
        print("자식 클래스의 메서드");
    }
}

이 예제에서 `Child` 클래스는 `MixinA` 믹스인을 통해
`methodA()` 메서드를 사용할 수 있게 됩니다.
즉, 믹스인은 다중 상속의 대안으로 코드 재사용을 가능하게 합니다.

6. 실전 예제: 플러터에서의 상속 활용

이제 플러터 애플리케이션에서 상속을 활용한 간단한 예제를
만들어보겠습니다. 여기서는 기본적인 UI 구성과 함께
상속을 사용하는 방법을 보여줍니다.

import 'package:flutter/material.dart';

void main() {
  runApp(MyApp());
}

class MyApp extends StatelessWidget {
  @override
  Widget build(BuildContext context) {
    return MaterialApp(
      home: HomeScreen(),
    );
  }
}

class HomeScreen extends StatelessWidget {
  @override
  Widget build(BuildContext context) {
    return Scaffold(
      appBar: AppBar(title: Text('상속 예제')),
      body: Center(
        child: Column(
          mainAxisAlignment: MainAxisAlignment.center,
          children: [
            ChildWidget(),
            SizedBox(height: 20),
            ParentWidget(),
          ],
        ),
      ),
    );
  }
}

class ParentWidget extends StatelessWidget {
  @override
  Widget build(BuildContext context) {
    return Text(
      '부모 클래스입니다.',
      style: TextStyle(fontSize: 24),
    );
  }
}

class ChildWidget extends ParentWidget {
  @override
  Widget build(BuildContext context) {
    return Text(
      '자식 클래스입니다.',
      style: TextStyle(fontSize: 24, color: Colors.blue),
    );
  }
}

위 코드는 두 개의 위젯 클래스를 설명합니다.
`ParentWidget`은 기본 텍스트를 출력하고,
`ChildWidget`은 `ParentWidget`을 상속받아
텍스트 색상을 변경합니다.
이처럼 상속을 통해 UI 위젯의 속성을 변경하거나
확장할 수 있습니다.

7. 요약

이번 강좌에서는 플러터에서의 상속의 개념과
그 필요성을 알아보았고, Dart에서의 상속 문법 및
메서드 오버라이딩, 믹스인과 같은 고급 개념에 대해 설명했습니다.
또한 실전 예제를 통해 상속이 어떻게 활용되는지
확인하였으며, 플러터 애플리케이션에서 상속을 효과적으로
사용할 수 있는 방법을 배우게 되었습니다.

상속은 객체 지향 프로그래밍의 중추적인 개념 중 하나로,
플러터 애플리케이션을 개발할 때도 매우 중요한 역할을 합니다.
향후 강좌에서는 상속을 더 확장하여 복잡한
애플리케이션을 개발하는 방법에 대해 이야기하겠습니다.
이 강좌를 통해 상속의 기본 개념을 이해하고,
이를 프로그래밍에 어떻게 적용할 수 있는지에 대한
통찰을 제공할 수 있기를 바랍니다.

작성자: 조광형 | 날짜: 2024년 11월 26일