본문 바로가기

Development/C#

추상클래스를 왜 사용해야 할까?

출처 : http://mrtint.tistory.com/678


왜 추상클래스를 사용해야할까요?

어떤 기술의 사용이라는게 좋은 취지에서 사용이 되었더라도 다른 부분에서의 예기치 못한 불협화음을 만들어 낼 수 있다. 클래스의 상속이 그러할지도 모르겠다. 상속을 설명하며 Animal 이라는 클래스와 Cat, Dog 라는 클래스는 IS 의 관계를 만드는 관계를 맺고 있다. 그러면서 생기는 논리적인 문제는 구체적이지 않은 Animal 이라는 클래스의 인스턴스를 만들 수 있다는 점이다.

Animal ani1 = new Animal();   
Animal ani2 = new Dog();   
Animal ani3 = new Cat();

 그럼 Animal 이라는 클래스로부터 Dog, Cat 이라는 클래스가 공유해야할 것들은 공유하되 직접적인 Animal 클래스의 인스턴스의 생성을 막으려면 어떤 방법을 써야 할지에 대해 고민해봤다. 바로 나온 답은 추상클래스를 사용하는 것이다. 추상클래스를 선언하는 방법은 아주 간단하다. 클래스의 선언 부에만 abstract 라는 키워드를 사용하면 된다. 그리고 기존에 override 가능한 메소드에 virtual 이라고 표시하여 가상 메소드를 만들어 준 것들에 대해서 역시 abstract 라는 키워드를 사용하여 추상 메소드로 변경을 해주면 된다. 더불어 기존 virtual 메소드의 내용을 지우고 선언만 해준다.

변경하면 결과는 아래와 같다.


public abstract class Animal   
{   
    private string name;   
    private string sound;   
  
    public Animal()   
    {   
        this.name = "동물";   
    }   
  
    public string Name   
    {   
        get { return name; }   
        set { name = value; }   
    }   
    public string Sound   
    {   
        get { return sound; }   
        set { sound = value; }   
    }   
  
    public void doWeeping()   
    {   
        Console.WriteLine("{0} : {1} 하고 울어댑니다.", name, sound);   
    }   
  
    public abstract void greeting();   
}  


이렇게 되면 Animal 은 직접 인스턴스를 생성할 수는 없지만 Cat이나 Dog 에서 공통적으로 있어야 하는 Attribute 들이나 doWeeping() 같은 메소드 그리고 프로퍼티들은 공유를 할 수 있게 되어서 보다 효율적인 클래스의 재사용을 가능하게 했다. 이렇게 되면 위에 처럼 ani1, ani2, ani3 변수를 선언하면서 ani1 의 선언은 불가능해진다.

여기까지만 보면 추상클래스를 만든다는 것이 상속할 것들은 가지고 있으되 자신의 인스턴스를 못만드는 클래스인 것 처럼만 비춰지는데 이는 분명 맞는 소리이긴 하지만 더 깊은 의미가 있다.

Animal 이라는 클래스가 구체화 된 일반 클래스였다면 이를 상속받는 클래스들은 greeting() 메소드와 같은 메소드를 반드시 구현해야하는 구속력은 갖고있지 않다. 하지만 반대로 위처럼 추상클래스가 된다면 이를 상속받는 클래스들은 반드시 추상화된 메소드를 오버라이드 해야만 하는 구속력이 생기게 되므로 문법적인 제한을 줄 수가 있다.

디자인 패턴에서는 Template Method Patterns 라는 패턴에서 주로 추상클래스가 쓰였던 기억이 난다. 추상클래스를 사용하여 오버라이드 된 메소드들로 다형성을 사용하여 유연한 소프트웨어 개발을 유도하는 패턴이다.