IT공부

[C#] 추상 클래스와 인터페이스의 차이

shine94 2025. 4. 14. 04:30

* 추상 클래스(abstract class)

   기본 구현과 상속을 통해 확장할 수 있는 기본 구현, 설계 뼈대를 제공

   일반 메서드와 virtual 메서드가 있으며, virtual 메서드만 오버라이드(재정의) 가능

   추상(abstract) 메서드는 반드시 재정의 필요

   상태(필드)와 생성자 가능

   단일 상속만 가능

 

* 인터페이스(interface)

   기능의 명세(정의)만 제공, 구현은 없음(C# 8.0 전 기준)

   C# 8.0 이후부터는 default 구현(바디 포함)도 가능

   상태(필드)와 생성자 불가

   다중 상속 가능

 

* 인터페이스는 "운전할 수 있는 자격증"과 같다

   "이 객체는 운전할 수 있는 기능을 반드시 가지고 있어야 한다"는 의미를 가진 기능 명세

using System;

interface ILicense
{
    void Drive();
}

class Bus : ILicense
{
    public void Drive()
    {
        Console.WriteLine("버스를 운전합니다.");
    }
}

class DumpTruck : ILicense
{
    public void Drive()
    {
        Console.WriteLine("덤프트럭을 운전합니다.");
    }
}

class CarAutoBy2 : ILicense
{
    public void Drive()
    {
        Console.WriteLine("2종 오토 차량을 운전합니다.");
    }
}

 

* 추상 클래스는 "자동차 설계도"와 같다

   "공통 부품은 기본 장착돼 있지만, 엔진은 차종마다 다르기 때문에 직접 만들어야 한다”는 의미를 가진 기본 구현 + 설계 뼈대

using System;

abstract class Car
{
    protected int handle;
    protected int wheel;
    protected int maxSpeed;

    public void MakeHandle()
    {
        Console.WriteLine("핸들 장착");
    }

    public void MakeWheel()
    {
        Console.WriteLine("바퀴 장착");
    }

    public abstract void MakeEngine();  // 추상 메서드 → 자식 클래스가 반드시 구현
}

class SportCar : Car
{
    public override void MakeEngine()
    {
        MakeHandle();
        MakeWheel();
        maxSpeed = 300;
        Console.WriteLine($"스포츠카 엔진 장착, 최고 속도: {maxSpeed}km/h");
    }
}

class SuvCar : Car
{
    public override void MakeEngine()
    {
        MakeHandle();
        MakeWheel();
        maxSpeed = 180;
        Console.WriteLine($"SUV 엔진 장착, 최고 속도: {maxSpeed}km/h");
    }
}

 

* 자바는

   모든 인스턴스 메서드는 기본적으로 virtual이기 때문에

   @Override만 붙이면 오버라이딩이 자동으로 허용된다

 

   "당연히 오버라이딩 가능 가능~~ㅎㅎ" → 유연함

 

* C#은

   기본적으로 오버라이딩을 허용하지 않는다

   오버라이딩을 하기 위해서는 반드시 virtual 키워드를 붙여야 허용된다

   따라서, 오버라이딩이 가능한 메서드는 반드시 virtual 또는 abstract이어야 한다

 

   "오버라이딩? 진짜 그럴 의도야? 그럼 virtual이라고 말해 안그럼 죽어도 안돼" → 명시적

 

* 나는 원래 인터페이스와 추상 클래스를 굳이 나눌 필요가 없다고 생각했다

   왜냐하면 추상 클래스만으로도 인터페이스의 역할까지 충분히 커버할 수 있다고 느꼈기 때문이다


   게다가 C# 8.0 이후에 인터페이스에 기본 구현(바디)를 작성할 수 있게 되면서,

   (물론 나는 자바를 먼저 사용했었고, 자바도 마찬가지였다)
   두 개념의 경계가 점점 모호해지고 있었고,

   그래서 나는 지금까지도 그 생각이 맞다고 생각하고 있었다

 

   다시 공부하는 과정에서

   (C와 C++, C#, Java가 섞이니 진짜 헷갈렸다 😢😢)

   검색과 자료 조사를 통해 그 의도의 배경을 이해할 수 있었다

 

   결국 언어 설계자가 인터페이스와 추상 클래스를 구분한 이유는,
   "의도가 다르면 문법도 달라야 한다"는 철학적인 기준 때문이라는 것이다

 

   즉,

   개발자의 의도를 코드로 명확히 표현하기 위해 두 개념을 형식적으로 구분한 것이고

 

   이걸 이해하고 나니,

   이제는 나도 왜 나눠야 하는지 머리가 아닌 몸으로 이해한 것 같다