C# - 상속: 초보자를 위한 종합 가이드

안녕하세요, 꿈을 가진 프로그래머 여러분! 오늘 우리는 C# 상속의 세계로 흥미로운 여정을 떠납니다. 프로그래밍에 새로운 사람이라면 걱정 마세요 - 나는 당신의 친절한 가이드가 되어, 이 개념을 함께 단계별로 탐구할 것입니다. 이 튜토리얼의 끝에 도달하면 상속과 그것이 코드를 더 효율적이고 체계적으로 만드는 방법에 대해 확고한 이해를 가질 것입니다.

C# - Inheritance

상속이란 무엇인가?

이제 구체적인 내용으로 들어가기 전에 간단한 비유로 시작해보겠습니다. 상속이란 상상 속 가족 트리를 만들고 있다고 생각해보세요. 그 트리에 있는 각 사람은 부모님으로부터 특정한 성향을 상속받죠? 프로그래밍에서의 상속은 이와 유사하게 작동합니다!

C#에서 상속은 새로운 클래스가 기존 클래스를 기반으로 만들어지는 메커니즘입니다. 새로운 클래스는 기존 클래스의 속성과 메서드를 상속받아, 부모님으로부터 눈 색이나 키를 상속받는 것과 같은 방식입니다.

기본 클래스와 파생 클래스

상속의 세계에서 우리는 두 가지 주요 역할을 가집니다:

  1. 기본 클래스 (또는 부모 또는 슈퍼클래스): 이는 공통된 속성과 메서드를 가지고 있는 원본 클래스입니다.
  2. 파생 클래스 (또는 자식 또는 서브클래스): 이는 기본 클래스로부터 상속받는 새로운 클래스입니다.

간단한 예제를 보겠습니다:

// 기본 클래스
public class Animal
{
public string Name { get; set; }
public int Age { get; set; }

public void Eat()
{
Console.WriteLine($"{Name} is eating.");
}
}

// 파생 클래스
public class Dog : Animal
{
public void Bark()
{
Console.WriteLine($"{Name} says Woof!");
}
}

이 예제에서 Animal은 기본 클래스이고, Dog은 파생 클래스입니다. Dog 클래스 선언에서 : Animal 부분은 C#에게 DogAnimal로부터 상속된다고 알리는 방법입니다.

이제 이 클래스들을 어떻게 사용할 수 있는지 보겠습니다:

Dog myDog = new Dog();
myDog.Name = "Buddy";
myDog.Age = 3;

myDog.Eat();  // Animal에서 상속받음
myDog.Bark(); // Dog에서 정의됨

이 코드를 실행하면 다음과 같은 출력을 볼 수 있습니다:

Buddy is eating.
Buddy says Woof!

이게 멋지지 않나요? Dog 클래스는 Animal 클래스의 NameAge 속성 그리고 Eat() 메서드에 접근할 수 있어, 모든 코드를 다시 작성할 필요 없이 사용할 수 있습니다!

기본 클래스 초기화

이제 궁금할 수도 있습니다, "파생 클래스 객체를 생성할 때 기본 클래스에 대해 초기 값을 설정하고 싶다면 어떻게 하나요?" 훌륭한 질문입니다! 이제 생성자를 사용하는 방법을 알아보겠습니다.

예제를 수정해보겠습니다:

public class Animal
{
public string Name { get; set; }
public int Age { get; set; }

public Animal(string name, int age)
{
Name = name;
Age = age;
}

public void Eat()
{
Console.WriteLine($"{Name} is eating.");
}
}

public class Dog : Animal
{
public Dog(string name, int age) : base(name, age)
{
// Dog에 대한 추가 초기화가 필요하다면 여기에 작성
}

public void Bark()
{
Console.WriteLine($"{Name} says Woof!");
}
}

이 업데이트된 버전에서는 Animal 클래스에 생성자를 추가했습니다. Dog 클래스의 생성자는 : base(name, age) 문법을 사용하여 기본 클래스 생성자를 호출하고 nameage 매개변수를 전달합니다.

이제 Dog 객체를 다음과 같이 생성할 수 있습니다:

Dog myDog = new Dog("Buddy", 3);
myDog.Eat();
myDog.Bark();

이전과 같은 출력을 생성할 것입니다:

Buddy is eating.
Buddy says Woof!

이제 NameAge 속성을 Dog 객체를 생성할 때 초기화할 수 있습니다.

C#에서 다중 상속

이제 흥미로운 변화를 보여드리겠습니다: C#은 클래스에 대해 다중 상속을 지원하지 않습니다. 이는 클래스가 직접 여러 개의 기본 클래스로부터 상속할 수 없음을 의미합니다.

하지만 걱정 마세요! C#은 인터페이스를 사용하여 이를 해결하는 지능적인_workaround를 제공합니다. 인터페이스는 클래스가 무엇을 해야 하는지 정의하지만, 그것을 어떻게 할지는 정의하지 않습니다.

예제를 보겠습니다:

public interface ISwimmable
{
void Swim();
}

public interface IFlyable
{
void Fly();
}

public class Bird : Animal, IFlyable
{
public Bird(string name, int age) : base(name, age) { }

public void Fly()
{
Console.WriteLine($"{Name} is flying.");
}
}

public class Fish : Animal, ISwimmable
{
public Fish(string name, int age) : base(name, age) { }

public void Swim()
{
Console.WriteLine($"{Name} is swimming.");
}
}

public class Duck : Animal, ISwimmable, IFlyable
{
public Duck(string name, int age) : base(name, age) { }

public void Swim()
{
Console.WriteLine($"{Name} is swimming.");
}

public void Fly()
{
Console.WriteLine($"{Name} is flying.");
}
}

이 예제에서 우리는 두 개의 인터페이스: ISwimmableIFlyable을 생성했습니다. Bird 클래스는 Animal을 상속하고 IFlyable을 구현합니다. Fish 클래스는 Animal을 상속하고 ISwimmable을 구현합니다. 그리고 Duck 클래스는 Animal을 상속하고 ISwimmableIFlyable 모두를 구현합니다!

이 클래스들을 사용해보겠습니다:

Bird myBird = new Bird("Tweety", 2);
myBird.Fly();

Fish myFish = new Fish("Nemo", 1);
myFish.Swim();

Duck myDuck = new Duck("Donald", 5);
myDuck.Swim();
myDuck.Fly();

이는 다음과 같은 출력을 생성할 것입니다:

Tweety is flying.
Nemo is swimming.
Donald is swimming.
Donald is flying.

이게 놀라운 것은 아닌가요? Duck 클래스는 떠다니고 날 수도 있어, C#이 클래스에 대해 다중 상속을 지원하지 않지만도 말입니다!

메서드 표

우리 예제에서 사용한 메서드를 요약하는 표를 보여드리겠습니다:

클래스/인터페이스 메서드 설명
Animal Eat() 동물이 먹고 있는 메시지를 출력합니다
Dog Bark() 개가 짖는 메시지를 출력합니다
ISwimmable Swim() 수영 메서드를 정의합니다
IFlyable Fly() 날아다니는 메서드를 정의합니다
Bird Fly() Fly 메서드를 구현합니다
Fish Swim() Swim 메서드를 구현합니다
Duck Swim(), Fly() Swim과 Fly 메서드를 모두 구현합니다

이제 여러분은 C#의 상속 기초를 다루고, 단순한 기본 및 파생 클래스에서 더 복잡한 인터페이스 사용 사례에 이르기까지 이해했습니다. 상속은 코드 재사용과 클래스 간의 논리적 관계를 만드는 데 유용한 도구입니다. 코드를 더 효율적이고 유지보수하기 쉽게 만들 수 있습니다.

프로그래밍 여정을 계속하면서 상속을 사용하여 복잡한 문제를 해결하는 다양한 방법을 발견할 것입니다. 이 개념을 연습하고 실험하는 것을 두려워하지 마세요. 행복한 코딩을 기원합니다!

Credits: Image by storyset