본문 바로가기
우아한 코딩

[C#] 상속과 Interface 구현, 어떤 것을 선택해야 할까?

by 피크인사이트 2024. 4. 5.
반응형

프로그래밍을 하며 클래스간의 관계를 정의할 경우 상속과 Interface 구현을 주로 사용하는데,

이 둘의 차이점과 각각의 장단점을 비교하여,

왜 Interface를 정의하고 구현하는 것이 더 좋은 선택인지 알아보겠습니다.

상속과 Interface 구현

1. 상속과 Interface 구현의 차이점

상속(Inheritance)

- 상속은 클래스 간의 계층적인 관계를 나타냅니다.

- 부모 클래스의 멤버(필드, 메서드)를 자식 클래스가 그대로 상속받아 사용할 수 있습니다.

- 상속은 is-a 관계이며, 자식 클래스가 부모 클래스의 하위 타입입니다.

- 클래스 간의 강한 결합을 가져오며, 부모 클래스의 변경은 자식 클래스에게 영향 줄 수 있습니다.

- 예시 : 동물을 나타내는 Animal 클래스가 있고, 각 동물들이 소리를 낼 수 있는지를 나타내는 기능 추가

class Animal
{
    // 동물의 공통 기능
}

class Cat : Animal
{
    public void MakeSound()
    {
        Console.WriteLine("Meow!");
    }
}

class Dog : Animal
{
    public void MakeSound()
    {
        Console.WriteLine("Woof!");
    }
}

 

위 예시처럼 각 동물들을 나타내는 클래스(Cat, Dog)가 Animal 클래스를 상속받아 소리를 내는 기능을 구현할 수 있습니다.

Interface 구현(Interface Implementation)

- Interface는 클래스가 특정 기능을 지원한다는 것을 나타내는 역할을 합니다.

- 클래스가 Interface를 구현하면, 그 Interface가 정의한 메서드를 반드시 구현해야 합니다.

- Interface는 has-a 관계를 나타내며, 클래스가 특정 기능을 가지고 있다는 것을 나타냅니다.

- 클래스 간의 느슨한 결합을 가져오며, 클래스의 변경이 Interface에 영향을 주지 않습니다.

- 예시 : 동물을 나타내는 Animal 클래스가 있고, 각 동물들이 소리를 낼 수 있는지를 나타내는 기능 추가

interface ISoundable
{
    void MakeSound();
}

class Cat : ISoundable
{
    public void MakeSound()
    {
        Console.WriteLine("Meow!");
    }
}

class Dog : ISoundable
{
    public void MakeSound()
    {
        Console.WriteLine("Woof!");
    }
}

 

이렇게 상속과 Interface 구현은 클래스 간의 관계를 다르게 표현하며, 프로그램의 요구사항에 따라 선택되어야 합니다.

 

3. Interface를 사용하는 예시

Interface를 사용하여 여러 클래스가 특정 동작을 공유하도록 설계할 수 있습니다.

예를 들어, 여러 도형(원, 사각형, 삼각형 등)이 있고 각 도형의 넓이를 계산하는 기능을 공통으로 제공하한 다고 가정해 보면,

interface IShape
{
    double CalculateArea(); //CalculateArea
}

class Circle : IShape
{
    public double Radius { get; set; }
    
    //넓이
    public double CalculateArea()
    {
        return Math.PI * Radius * Radius;
    }
}
//원..
class Rectangle : IShape
{
    public double Width { get; set; }
    public double Height { get; set; }
    
   //원..
    public double CalculateArea()
    {
        return Width * Height;
    }
}

 

위 예시에서는 IShape 인터페이스를 정의하여 CalculateArea 메서드를 가지도록 하였습니다.

그리고 Circle 클래스와 Rectangle 클래스가 이  IShape  인터페이스를 구현하여 각각의 도형 넓이를 계산하는 기능을 제공합니다.

 

4. 상속의 사용 사례

상속은 클래스 간에 공통적인 기능이 많이 존재하고, 상위 클래스가 여러 하위 클래스의 공통 코드를 제공할 때 유용하게 사용됩니다.

예를 들어, 여러 종류의 동물이 있고 각 동물들이 공통적으로 움직이는 기능을 가질 때 상속을 사용할 수 있습니다.

class Animal
{
    public void Move()
    {
        Console.WriteLine("Animal is moving.");
    }
}

class Bird : Animal
{
    public void Fly()
    {
        Console.WriteLine("Bird is flying.");
    }
}

class Fish : Animal
{
    public void Swim()
    {
        Console.WriteLine("Fish is swimming.");
    }
}

 

위 예시에서는 Animal 클래스가 움직이는 기능을 제공하고, Bird 클래스와 Fish 클래스가 이를 상속받아 각각의 추가적인 기능인 Fly와 Swim 메서드를 구현하고 있습니다.

이렇게 상속을 사용하여 공통된 기능을 재사용할 수가 있고, 코드의 중복도 피할 수 있습니다.

 

5. 어떤 것을 선택해야 할까?

프로그램의 요구 사항을 고려하여 상속과 Interface를 선택하는 것이 중요합니다.

일반적으로는 Interface를 우선적으로 고려하고,

상속은 특정 상황에서 사용하는 것이 좋습니다.

Interface를 선택하는 경우

- 클래스 간의 결합을 최소화하고 유연성을 높이고자 할 때

- 다중 구현이 필요할 때 - 코드의 가독성과 유지보수성을 높이고자 할 때

- 특정 기능을 지원하는 여러 클래스를 통일된 방식으로 다루고자 할 때

 

상속을 선택하는 경우

- 부모 클래스의 구현을 상속받아 재사용하고자 할 때

- is-a 관계가 명확하게 존재하고, 상위 클래스의 모든 특성을 하위 클래스가  갖고 있을 때

- 부모 클래스의 기능을 확장하거나 변형하고자 할 때


마무리

이상과 같이 살펴본 대로 상속과 Interface는 클래스 간의 관계를 다르게 표현하며, 각각의 장단점을 가지고 있기 때문에

프로그램의 요구 사항을 고려하여 적절한 방식을 선택하여 사용해야 합니다.

 

<참고>

 

 

 

 

반응형