혼동하기 쉬운 메서드 숨기기 (Method Hiding)

[제목] 혼동하기 쉬운 메서드 숨기기 (Method Hiding)

클래스 계층 구조에서 동일한 메서드명을 갖는 메서드들이 상속 구조 내에서 존재할 때, 어떤 메서드가 호출되는지 혼동될 경우가 있다. Base 클래스의 메서드를 호출하고자 했는데, 파생클래스의 메서드가 호출될 수도 있고, 또 그 반대의 경우도 발생할 수 있다.

아래의 코드에는 3개의 상속관계의 클래스들이 있다. 각 클래스에는 동일한 메서드 Eat()가 존재한다. 차이점은 각기 다른 파라미터 타입을 가지고 있다는 점이다. 만약 Bulldog 클래스 객체를 생성하고 정수형 파라미터를 전달했을 때, Animal, Dog, Bulldog중 어느 클래스의 메서드를 호출하게 될 것인가?

class Animal
{
    public void Eat(int kg)
    {
        Console.WriteLine("Animal.Eat: {0} kg", kg);
    }
}

class Dog : Animal
{
    public void Eat(long kg)
    {
        Console.WriteLine("Dog.Eat: {0} kg", kg);
    }        
}

class Bulldog : Dog
{
    public void Eat(string kg)
    {
        Console.WriteLine("Bulldog.Eat: {0} kg", kg);
    }
}

class Program
{
    static void Main(string[] args)
    {
        Bulldog obj = new Bulldog();
        int kg = 2;

        obj.Eat(kg);  // #1

        ((Animal)obj).Eat(kg);  // #2
    }
}

메서드 검색은 동일 메서드명으로 (동일 수의) 동일 타입의 파라미터 혹은 호환 가능한 타입의 파라미터를 발견할 때까지 계속 상위 클래스를 찾아 가면서 진행된다. 그리고, 일단 중간에 조건에 맞는 메서드를 발견하면 검색을 중지하고 해당 메서드를 사용한다.

#1의 obj.Eat() 메서드는 우선 Bulldog 클래스 객체이므로, Bulldog 클래스내의 메서드들을 검사한다. Bulldog 클래스내에 Eat()라는 메서드가 존재하지만, 파라미터가 string이므로 암시적으로 변환(implicitly conversion)이 불가능하다. 따라서, 상위 클래스인 Dog클래스에서 Eat()를 찾게 된다. Dog클래스는 long 파라미터를 갖는 Eat 메서드가 있는데, int 타입인 변수 kg값을 long으로 변환하는 것이 가능하므로 이 Dog클래스의 Eat 메서드를 실행하게 된다. 일단, 이렇게 메서드가 발견되면, 상위 클래스(Animal)가 꼭 맞는 int 타입의 파리미터를 갖는 메서드 Eat()를 갖고 있더라고 검색을 멈추고 발견된 메서드를 사용하게 된다.

만약 이러한 자동 메커니즘이 아니라 사용자가 특정 클래스의 메서드를 지정해서 호출하고 싶다면, #2에서 처럼 해당 클래스로 캐스팅한 후 메서드를 호출하면 된다.



본 웹사이트는 광고를 포함하고 있습니다. 광고 클릭에서 발생하는 수익금은 모두 웹사이트 서버의 유지 및 관리, 그리고 기술 콘텐츠 향상을 위해 쓰여집니다.