[C#] 상속과 다형성
[C#] 상속과 다형성
상속과 다형성
상속
- 상속의 개념:
- 상속은 기존의 클래스(부모 클래스 또는 상위 클래스)를 확장하거나 재사용하여 새로운 클래스(자식 클래스 또는 하위 클래스)를 생성하는 것.
- 자식 클래스는 부모 클래스의 멤버(필드, 메서드, 프로퍼티 등)를 상속받아 사용할 수 있다.
- 상속을 통해 부모 클래스의 기능을 확장하거나 수정하여 새로운 클래스를 정의할 수 있다.
- 상속의 장점:
- 코드의 재사용성: 상속을 통해 기존 클래스의 코드를 재사용할 수 있으므로, 반복적인 코드 작성을 줄일 수 있다.
- 계층 구조의 표현: 클래스 간의 계층 구조를 표현하여 코드의 구조를 명확하게 표현할 수 있다.
- 유지보수성의 향상: 상속을 통해 기존 클래스의 수정이 필요한 경우, 해당 클래스만 수정하면 된다. 이로써 코드의 유지보수성이 향상된다.
- 상속의 종류:
- 단일 상속: 하나의 자식 클래스가 하나의 부모 클래스만 상속받는 것을 말한다. C#에서는 단일 상속만을 지원한다.
- 다중 상속: 하나의 자식 클래스가 여러 개의 부모 클래스를 동시에 상속받는 것을 말한다. C#은 다중 상속을 지원하지 않습니다.
- 인터페이스 상속: 클래스가 인터페이스를 상속받는 것을 말한다. 인터페이스는 다중 상속을 지원하며, 클래스는 하나의 클래스와 여러 개의 인터페이스를 동시에 상속받을 수 있다.
- 상속의 특징:
- 부모 클래스의 멤버에 접근:
- 자식 클래스는 상속받은 부모 클래스의 멤버에 접근할 수 있으며, 이를 통해 부모 클래스의 기능을 재사용할 수 있다.
- 메서드 재정의:
- 자식 클래스는 부모 클래스의 메서드를 재정의하여 자신에게 맞게 수정할 수 있다. 이를 통해 다형성(Polymorphism)을 구현할 수 있다.
- 상속의 깊이 :
- 클래스는 다수의 계층적인 상속 구조를 가질 수 있다. 부모 클래스가 또 다른 클래스의 자식 클래스가 될 수 있으며, 이를 통해 상속의 계층 구조를 형성할 수 있다.
- 상속의 깊이가 깊어질수록 클래스 간의 관계가 복잡해질 수 있으므로, 적절한 상속의 깊이를 유지하고 상속을 적절하게 사용하는 것이 중요한다.
- 부모 클래스의 멤버에 접근:
- 접근 제한자와 상속:
- 상속 관계에서 멤버의 접근 제한자는 중요한 역할을 한다. 부모 클래스의 멤버의 접근 제한자에 따라 자식 클래스에서 해당 멤버에 접근할 수 있는 범위가 결정된다.
- 접근 제한자를 통해 상속된 멤버의 가시성을 조절하여 캡슐화와 정보 은닉을 구현할 수 있다.
1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
// 부모 클래스
public class Animal
{
public string Name { get; set; }
public void Eat()
{
Console.WriteLine("Animal is eating.");
}
public void Sleep()
{
Console.WriteLine("Animal is sleeping.");
}
}
// 자식 클래스
public class Dog : Animal
{
public int Age { get; set; }
}
// 자식 클래스
public class Cat : Animal
{
public int Age { get; set; }
}
다중 상속을 사용하지 않는 이유
다이아몬드 문제(Diamond Problem): 다중 상속을 허용하면 한 클래스가 두 개 이상의 부모 클래스로부터 동일한 멤버를 상속받을 수 있다. 이 경우, 같은 이름의 멤버를 가지고 있을 때 어떤 부모 클래스의 멤버를 사용해야 하는지 모호해진다.
설계의 복잡성 증가: 클래스가 다중 상속을 받을 경우, 어떤 클래스로부터 어떤 멤버를 상속받을지 결정해야 한다. 이로 인해 클래스 간의 상속 관계를 파악하기 어려워지고 코드의 유지 보수성이 저하될 수 있다.
이름 충돌과 충돌 해결의 어려움: 다중 상속을 허용하면 여러 부모 클래스로부터 상속받은 멤버들이 이름이 충돌할 수 있다. 이러한 충돌을 해결하기 위해 충돌하는 멤버를 재정의해야 하거나 명시적으로 부모 클래스를 지정해야 할 수 있다. 이는 코드의 복잡성을 증가시키고 오류 발생 가능성을 높입니다.
설계의 일관성과 단순성 유지: C#은 단일 상속을 통해 설계의 일관성과 단순성을 유지하고자 한다. 단일 상속을 통해 클래스 간의 관계를 명확하게 만들고 코드의 가독성과 이해도를 높일 수 있다. 또한 인터페이스를 사용하여 다중 상속이 필요한 경우에도 유사한 기능을 구현할 수 있다.
다향성
- 가상(Virtual) 메서드
- 가상 메서드는 기본적으로 부모 클래스에서 정의되고 자식 클래스에서 재정의할 수 있는 메서드입니다.
- 가상 메서드는
virtual키워드를 사용하여 선언되며, 자식 클래스에서 필요에 따라 재정의될 수 있다. - 이를 통해 자식 클래스에서 부모 클래스의 메서드를 변경하거나 확장할 수 있다.
1 2 3 4 5 6 7 8 9 10 11 12 13 14 15 16 17 18 19 20 21 22 23 24 25
public class Unit { public virtual void Move() { Console.WriteLine("두발로 걷기"); } public void Attack() { Console.WriteLine("Unit 공격"); } } public class Marine : Unit { } public class Zergling : Unit { public override void Move() { Console.WriteLine("네발로 걷기"); } }
- 추상(Abstract) 클래스와 메서드
- 추상 클래스는 직접적으로 인스턴스를 생성할 수 없는 클래스.
- 주로 상속을 위한 베이스 클래스로 사용.
- 추상 클래스는
abstract키워드를 사용하여 선언되며, 추상 메서드를 포함할 수 있다. - 추상 메서드는 구현부가 없는 메서드로, 자식 클래스에서 반드시 구현되어야 한다.
1 2 3 4 5 6 7 8 9 10 11 12 13 14 15 16 17 18 19 20
abstract class Shape { public abstract void Draw(); } class Circle : Shape { public override void Draw() { Console.WriteLine("Drawing a circle"); } } class Square : Shape { public override void Draw() { Console.WriteLine("Drawing a square"); } }
오버라이딩 과 오버로딩
오버라이딩(Overriding)과 오버로딩(Overloading)은 객체 지향 프로그래밍에서 다른 개념을 나타낸다.
- 오버라이딩(Overriding)
- 부모 클래스에서 이미 정의된 메서드를 자식 클래스에서 재정의하는 것을 의미한다.
- 이는 상속 관계에 있는 클래스 간에 발생하며, 메서드의 이름, 매개변수 및 반환타입이 동일해야 한다.
- 오버라이딩을 통해 자식 클래스는 부모 클래스의 메서드를 재정의하여 자신에게 맞는 동작을 구현할 수 있다.
1 2 3 4 5 6 7 8 9 10 11 12 13 14 15 16 17 18 19 20 21 22 23
public class Shape { public virtual void Draw() { Console.WriteLine("Drawing a shape."); } } public class Circle : Shape { public override void Draw() { Console.WriteLine("Drawing a circle."); } } public class Rectangle : Shape { public override void Draw() { Console.WriteLine("Drawing a rectangle."); } }
- 오버로딩(Overloading)
- 동일한 메서드 이름을 가지고 있지만, 매개변수의 개수, 타입 또는 순서가 다른 여러 개의 메서드를 정의하는 것을 의미한다.
- 오버로딩을 통해 동일한 이름을 가진 메서드를 다양한 매개변수 조합으로 호출할 수 있다.
1 2 3 4 5 6 7 8 9 10 11 12
public class Calculator { public int Add(int a, int b) { return a + b; } public int Add(int a, int b, int c) { return a + b + c; } }
- 오버라이딩(Overriding)
This post is licensed under CC BY 4.0 by the author.