Notice
Recent Posts
Recent Comments
Link
«   2024/05   »
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 28 29 30 31
Archives
Today
Total
05-16 20:20
관리 메뉴

nomad-programmer

[Programming/C#] 추상 클래스2 (interface와 class 사이) 본문

Programming/C#

[Programming/C#] 추상 클래스2 (interface와 class 사이)

scii 2020. 9. 11. 02:20

추상 클래스는 인터페이스와 달리 "구현"을 가질 수 있다. 하지만 클래스와는 달리 인스턴스를 가질 수 없다. 한마디로 추상 클래스는 구현을 갖되 인스턴스는 만들지 못한다.

abstract class 클래스이름
{
    // 클래스와 동일하게 구현
}

추상 클래스가 인터페이스와 클래스의 중간에 있다고 했지만 추상 클래스는 클래스에 더 가깝다. 추상 클래스의 접근성이 그 예이다. 클래스와 똑같다. 인터페이스에서는 모든 메소드가 public으로 선언되는 반면, 클래스는 한정자를 명시하지 않으면 모든 메소드가 private로 선언된다.
한편, 추상 클래스에는 인스턴스를 만들 수 없는 점 외에도 클래스와 다른 점이 또 하나 있다. 그것은 바로 "추상 메소드 (Abstract Method)" 를 가질 수 있다는 사실이다.
추상 메소드는 추상 클래스가 한편으로 인터페이스의 역할도 할 수 있게 해주는 장치이다. 추상 클래스를 상속하는 클래스들이 반드시 이 메소드를 갖고 있을 거라는 "약속" 인 것이다. 

추상 메소드의 기본 접근성

추상 메소드의 기본 접근성을 어떻게 될까? 인터페이스처럼 public? 아니면 클래스처럼 private? 답은 "둘 다" 이다. 
추상 클래스나 클래스는 그 안에서 선언되는 모든 필드, 메소드, 프로퍼티, 이벤트 모두 접근 한정자를 명시하지 않으면 private이다. 여기에는 추상 메소드도 예외가 될 수 없다. 하지만 "약속" 역할을 하는 추상 메소드가 private면 의미상 문제가 있다. 그리고 그렇게 둘 수는 없다. 그래서 C# 컴파일러는 추상 메소드가 반드시 public, protected, internal, protected internal 한정자 중 하나로 수식될 것을 강요한다.
이렇게 하면 클래스의 접근성 원칙도, 인터페이스의 접근성 원칙도 지켜질 수 있다. 

abstract class AbstractBase
{
     public abstract void SomeMethod();
}

class Derived : AbstractBase
{
    public override void SomeMethod()
    {
        // something
    }
}
추상 클래스가 또 다른 추상 클래스를 상속하는 경우

추상 클래스는 또 다른 추상 클래스를 상속할 수 있다. 이 경우 자식 추상 클래스는 부모 추상 클래스의 추상 메소드를 구현하지 않아도 된다. 추상 메소드는 생성할 클래스에서 구현하면 된다.

추상 클래스의 예제

using System;

namespace CSharpExample
{
    abstract class AbstractBase
    {
        protected void PrivateMethodA()
        {
            Console.WriteLine("AbstractBase.PrivateMethodA()");
        }

        public void PublicMethodA()
        {
            Console.WriteLine("AbstractBase.PublicMethodA()");
        }

        public abstract void AbstractMethodA();
    }

    class Derived: AbstractBase
    {
        public override void AbstractMethodA()
        {
            Console.WriteLine("Derived.AbstractMethodA()");
            PrivateMethodA();
        }
    }

    class MainApp
    {
        static int Main(string[] args)
        {
            AbstractBase obj = new Derived();
            obj.AbstractMethodA();
            obj.PublicMethodA();

            return 0;
        }
    }
}


/* 결과

Derived.AbstractMethodA()
AbstractBase.PrivateMethodA()
AbstractBase.PublicMethodA()

*/

추상 클래스를 사용하는 이유

추상 클래스는 일반 클래스가 가질 수 있는 구현과 더불어 추상 메소드를 가지고 있다 (물론, 추상 메소드가 없는 추상 클래스도 문법적으로 하자가 있는 것은 아니지만, 실질적으로 별 의미가 없는 코드이다).
추상 메소드는 추상 클래스를 사용하는 프로그래머가 그 기능을 정의하도록 강제하는 장치이다.

추상 클래스가 없었다면 그냥 메소드를 선언한 후 클래스에 대한 메뉴얼을 작성해서 코드와 함께 배포해야 한다. 하지만 추상 클래스를 이용한다면 이러한 설명이 필요 없다. 추상 클래스와 추상 메소드 자체가 이런 설명을 담고 있기 때문이다.
추상 클래스를 이용하는 다른 프로그래머가 파생 클래스를 만들어야 하며 모든 추상 메소드를 구현해야 한다는 사실을 잊어버린다 해도, 컴파일러가 상기시켜줄 것이다. 이것이 추상 클래스를 사용하는 이유이다.

Comments