[C#] 추상 클래스(Abstract Class)와 인터페이스(Interface)

Running boy·2023년 8월 6일
0

컴퓨터 공학

목록 보기
10/36

추상 클래스(Abstract Class)

추상 클래스로 정의된 경우 new를 사용해 스스로 객체가 될 수 없고 추상 메서드를 가질 수 있다. (일반 메서드 또한 당연히 가질 수 있다.)

abstract class AbstractClass
{
    public abstract void AbstractMethod();
    public void GeneralMethod()
    {
        Console.WriteLine("General Method");
    }
}
AbstractClass test = new AbstractClass(); // 컴파일 에러

추상 메서드(Abstract Method)

구현되지 않은 가상 메서드이다.

일반 클래스에서 선언할 수 없고 추상 클래스에서만 선언할 수 있다. (인터페이스에서도 가능하긴 하지만 딱히 의미가 없다.)

가상 메서드와 다른 점은 자식 클래스에서 재정의가 강제된다는 것이다.

class Test : AbstractClass
{
    public override void AbstractMethod()
    {
        
    }
}

인터페이스(Interface)

클래스 문법과 비슷하게 정의하지만 인터페이스는 클래스가 아니며, 0개 이상의 메서드의 선언만 포함할 수 있다. (프로퍼티는 내부적으론 메서드로 구현되므로 인터페이스에 포함될 수 있다.)

스스로 객체가 될 수 없다는 점, 상속 받은 클래스가 멤버를 반드시 구현해야 된다는 점이 추상 클래스와 유사하다.

비록 인터페이스 자체는 객체가 될 수 없지만 인터페이스를 상속 받은 객체는 인터페이스로서 접근이 가능하다.

interface IWalkable
{
    void Walk();
}

class Person : IWalkable
{
    public void Walk()
    {
        Console.WriteLine("Walk");
    }
}
IWalkable walkable = new Person();
walkable.Walk();

또한 인터페이스는 그 자체로서도 의미를 갖는다.

빈 인터페이스를 상속하여 클래스를 분류할 수 있다.

interface IWalkable {}

class Person : IWalkable
{
    public void Walk()
    {
        Console.WriteLine("Walk");
    }
}

class Fish
{
    public void Walk()
    {
        Console.WriteLine("Can't Walk");
    }
}
Person person = new Person();
Fish fish = new Fish();

if (person is IWalkable) // True
{
    person.Walk();
}
if (fish is IWalkable) // False
{
    fish.Walk();
}

인터페이스를 다중 상속할 경우 메서드의 시그니처가 겹치는 경우가 생길 수 있다.

이 경우 인터페이스를 구현하는 과정에서 메서드의 정의가 겹쳐서 특정 인터페이스만의 기능을 구현할 수 없게 된다.

public interface IControl
{
    void Paint();
}
public interface ISurface
{
    void Paint();
}
public class SampleClass : IControl, ISurface
{
    public void Paint()
    {
        Console.WriteLine("Paint method in SampleClass");
    }
}
SampleClass sampleClass = new SampleClass();
IControl control = sampleClass;
ISurface surface = sampleClass;

sampleClass.Paint();
control.Paint();
surface.Paint();

// 출력:
// Paint method in SampleClass
// Paint method in SampleClass
// Paint method in SampleClass

이를 해결하기 위해 C#은 아래와 같이 인터페이스의 메서드를 구현할 때 인터페이스를 명시할 수 있는 기능을 지원한다.

명시적 인터페이스 구현

public class SampleClass : IControl, ISurface
{
    void IControl.Paint()
    {
        Console.WriteLine("IControl.Paint");
    }
    void ISurface.Paint()
    {
        Console.WriteLine("ISurface.Paint");
    }
}

인터페이스를 명시할 경우 기존 표현 방식과 크게 두가지 차이를 가진다.
1. public 접근 제한자를 생략해야 한다.
2. 특정 인터페이스의 기능을 구현했다고 명시했으므로 반드시 형변환을 거쳐야 한다.

SampleClass sampleClass = new SampleClass();
IControl control = sampleClass;
ISurface surface = sampleClass;

sampleClass.Paint(); // 컴파일 에러가 발생한다.
control.Paint();
surface.Paint();

추상 클래스와 인터페이스의 차이점

  1. 추상 클래스는 일반 메소드를 정의할 수 있지만 인터페이스는 선언만 가능하다.
  2. 인터페이스는 다중 상속이 가능하다.
  3. 추상 클래스의 추상 메서드는 접근 제한자 설정이 가능하지만(private 제외) 인터페이스를 상속받은 경우 반드시 public으로 설정해야 한다.(단 인터페이스를 명시할 경우 public 생략 가능)
  4. 추상 클래스의 상속은 재정의, 인터페이스의 상속은 구현의 개념이다. 따라서 추상 메서드의 재정의는 override 키워드가 붙는다.

참고 자료
시작하세요! C# 10 프로그래밍 - 정성태

profile
Runner's high를 목표로

0개의 댓글