c# 상속, 다향성(가상 메서드)
개요
상속, 다향성에 대해서 알아보겠습니다
내용 - 상속이란
- 상속은 기존의 클래스(부모 클래스 또는 상위 클래스)를 확장하거나 재사용하여 새로운 클래스(자식 클래스 또는 하위 클래스)를 생성하는 것입니다.
- 자식 클래스는 부모 클래스의 멤버(필드, 메서드, 프로퍼티 등)를 상속받아 사용할 수 있습니다.
- 상속을 통해 부모 클래스의 기능을 확장하거나 수정하여 새로운 클래스를 정의할 수 있습니다.
상속 장점
- 코드의 재사용성: 상속을 통해 기존 클래스의 코드를 재사용할 수 있으므로, 반복적인 코드 작성을 줄일 수 있습니다.
- 계층 구조의 표현: 클래스 간의 계층 구조를 표현하여 코드의 구조를 명확하게 표현할 수 있습니다.
- 유지보수성의 향상: 상속을 통해 기존 클래스의 수정이 필요한 경우, 해당 클래스만 수정하면 됩니다. 이로써 코드의 유지보수성이 향상됩니다.
상속의 종류
- 단일 상속: 하나의 자식 클래스가 하나의 부모 클래스만 상속받는 것을 말합니다. C#에서는 단일 상속만을 지원합니다.
- 다중 상속: 하나의 자식 클래스가 여러 개의 부모 클래스를 동시에 상속받는 것을 말합니다. C#은 다중 상속을 지원하지 않습니다.
- 인터페이스 상속: 클래스가 인터페이스를 상속받는 것을 말합니다. 인터페이스는 다중 상속을 지원하며, 클래스는 하나의 클래스와 여러 개의 인터페이스를 동시에 상속받을 수 있습니다.
상속의 특징
- 부모 클래스의 멤버에 접근:
- 자식 클래스는 상속받은 부모 클래스의 멤버에 접근할 수 있으며, 이를 통해 부모 클래스의 기능을 재사용할 수 있습니다.
- 메서드 재정의:
- 자식 클래스는 부모 클래스의 메서드를 재정의하여 자신에게 맞게 수정할 수 있습니다. 이를 통해 다형성(Polymorphism)을 구현할 수 있습니다.
- 상속의 깊이 :
- 클래스는 다수의 계층적인 상속 구조를 가질 수 있습니다. 부모 클래스가 또 다른 클래스의 자식 클래스가 될 수 있으며, 이를 통해 상속의 계층 구조를 형성할 수 있습니다.
- 상속의 깊이가 깊어질수록 클래스 간의 관계가 복잡해질 수 있으므로, 적절한 상속의 깊이를 유지하고 상속을 적절하게 사용하는 것이 중요합니다.
접근 제한자와 상속
- 상속 관계에서 멤버의 접근 제한자는 중요한 역할을 합니다. 부모 클래스의 멤버의 접근 제한자에 따라 자식 클래스에서 해당 멤버에 접근할 수 있는 범위가 결정됩니다.
- 접근 제한자를 통해 상속된 멤버의 가시성을 조절하여 캡슐화와 정보 은닉을 구현할 수 있습니다.
상속 예제 코드
public class Animal
{
public string Name { get; set; }
public int Age { get; set; }
public void Eat()
{
Console.WriteLine("Animal is eating.");
}
public void Sleep()
{
Console.WriteLine("Animal is sleeping.");
}
}
// 자식 클래스
public class Dog : Animal
{
public void Bark()
{
Console.WriteLine("Dog is bark");
}
}
public class Cat : Animal
{
public void Meow()
{
Console.WriteLine("Cat is meow");
}
}
static void Main(string[] args)
{
Dog dog = new Dog();
dog.Name = "Bobby";
dog.Age = 3;
dog.Eat();
dog.Sleep();
dog.Bark();
Cat cat = new Cat();
cat.Name = "Bobby";
cat.Age = 3;
cat.Eat();
cat.Sleep();
cat.Meow();
}
이와같은 코드가 있을때 cat 한테만 다른 Sleep을 배정해 주고 싶을때 사용하는 방법이 가상 메서드이다.
내용 - 다향성
같은 타입이지만 다양한 동작을 수행할 수 있는 능력
내용 - 가상 메서드
- 가상 메서드는 기본적으로 부모 클래스에서 정의되고 자식 클래스에서 재정의할 수 있는 메서드입니다.
- 가상 메서드는 virtual 키워드를 사용하여 선언되며, 자식 클래스에서 필요에 따라 재정의될 수 있습니다.
- 이를 통해 자식 클래스에서 부모 클래스의 메서드를 변경하거나 확장할 수 있습니다.
가상 메서드 예시 코드
public class Unit
{
public virtual void Move() //virtual을 적어 넣으면 '자식이 Move를 재정의 했을 수도 있다' 고 알려주는 거다.
{
Console.WriteLine("두발로 걷기");
}
public void Attack()
{
Console.WriteLine("Unit 공격");
}
}
public class Marine : Unit
{
}
public class Zergling : Unit
{
public override void Move() // override를 통해 재정의를 했다고 알려주는 거다.
{
Console.WriteLine("네발로 걷기");
}
}
내용 - 오버라이딩 과 오버로딩 구분하기
오버라이딩(Overriding)
- 부모 클래스에서 이미 정의된 메서드를 자식 클래스에서 재정의하는 것을 의미합니다.
- 이는 상속 관계에 있는 클래스 간에 발생하며, 메서드의 이름, 매개변수 및 반환타입이 동일해야 합니다.
- 오버라이딩을 통해 자식 클래스는 부모 클래스의 메서드를 재정의하여 자신에게 맞는 동작을 구현할 수 있습니다.
오버라이딩 예제 코드
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.");
}
}
Shape shape1 = new Circle();
Shape shape2 = new Rectangle();
shape1.Draw(); // Drawing a circle.
shape2.Draw(); // Drawing a rectangle.
오버로딩(Overloading)
- 동일한 메서드 이름을 가지고 있지만, 매개변수의 개수, 타입 또는 순서가 다른 여러 개의 메서드를 정의하는 것을 의미합니다.
- 오버로딩을 통해 동일한 이름을 가진 메서드를 다양한 매개변수 조합으로 호출할 수 있습니다.
오버로딩 예제 코드
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;
}
}
Calculator calc = new Calculator();
int result1 = calc.Add(2, 3); // 5
int result2 = calc.Add(2, 3, 4); // 9