728x90
반응형

객체 지향 언어의 4대 기본 원칙 중 마지막 원칙인 다형성에 대해 알아보자.

객체 지향 언어의 4대 기본 원칙 :

  • 캡슐화 (Encapsulation)
  • 추상화 (Abstraction)
  • 상속 (Inheritance)
  • 다형성 (Polymorphism)

지난 포스트에서 다룬 상속은 사실 다형성을 위해서 사용되는 경우가 더 많다. 다형성은 "여러가지 형태를 갖는 것을 허용한다"는 뜻이다.

이전 포스트에서 사용했던 예제를 다시 한 번 들여다보자.

class Program
{
    static void Main(string[] args)
    {
        Dog myDog = new Puppy();
        myDog.Bark();
        //실행결과 --> 삑삑!
    }
}
public class Dog
{
    public virtual void Bark()
    {
        Console.WriteLine("멍멍!");
    }
}

public class Puppy : Dog
{
    public override void Bark()
    {
        Console.WriteLine("삑삑!");
    }
}

위 예제에서 Main함수를 보면 myDog라는 변수를 Dog로 선언했는데 실제로 생성한 객체는 Dog의 자식클래스인 Puppy이다.

이렇게 부모클래스로 선언된 변수에 자식클래스들도 할당될 수 있도록 허용한 것이 다형성이다. (반대로 자식클래스에 부모클래스를 할당하는 것은 불가능하다.)

다형성이 왜 필요한지 생각해보기 위해 간단한 예제를 만들어보자.

class Program
    {
    static void Main(string[] args)
    {
        List<Dog> myDogs = new List<Dog>();

        Dog dog1 = new Dog();
        myDogs.Add(dog1);
        Dog dog2 = new Puppy();
        myDogs.Add(dog2);
        Dog dog3 = new FakeDog();
        myDogs.Add(dog3);

        foreach(Dog dog in myDogs)
        {
            dog.Bark();
        }
    }
}

public class Dog
{
    public virtual void Bark()
    { 
        Console.WriteLine("멍멍!");
    }
}

public class Puppy : Dog
{
    public override void Bark()
    {
        Console.WriteLine("삑삑!");
    }
}

public class FakeDog : Dog
{
    public override void Bark()
    {
        Console.WriteLine("야옹~!");
    }
}

위 예제를 보면 Dog를 담을 수 있는 ListDog뿐만 아니라 Dog의 자식 클래스인 PuppyFakeDog도 들어가는 것을 볼 수 있다. 만약 다형성을 허용하지 않았다면. List<Dog>, List<Puppy>, List<FakeDog>를 모두 별도로 만들어 각각 따로 관리해야했을 것이다. 우리는 다형성을 이용해서 자료를 훨씬 체계적으로 관리 할 수 있다. 뿐만 아니라 클래스간의 의존성을 낮춰 느슨한 결합이 가능하게 한다. 느슨한 결합에 대해서는 디자인 패턴을 공부하면서 조금 더 알아보자.

마지막으로 지난 포스트 상속편에서 new키워드를 이용해서 부모클래스의 메소드를 변경했을 때 실행결과가 달라졌던 이유를 다시 한 번 생각해보자.

class Program
{
    static void Main(string[] args)
    {
        Puppy myPuppy = new Puppy();
        myPuppy.Bark();
        //실행결과 --> 삑삑!
        Dog myDog = new Puppy();
        myDog.Bark();
        //실행결과 --> 멍멍!
    }
}

public class Dog
{
    public void Bark()
    { 
        Console.WriteLine("멍멍!");
    }
}

public class Puppy : Dog
{
    public new void Bark() // new 키워드를 이용해 부모 메소드를 가린다.
    {
        Console.WriteLine("삑삑!");
    }
}

위 예제에서 보면 myPuppymyDog 변수 모두 Puppy 객체를 가지고 있지만 선언된 데이터 형태에 따라서 "멍멍"이라고 짖기도 하고 "삑삑"이라고 짖기도 한다. 이건 다형성의 원칙을 훼손하는 케이스다. 선언된 데이터 타입이 어떻든 Puppy는 "삑삑"하고 짖어야하지 않을까? 이러한 이유로 new키워드를 이용해 부모클래스의 함수를 변경하는 것은 지양해야한다.

728x90
반응형

+ Recent posts