C#은 자바의 장점을 수용하고,  자바가 모델로 삼은 C++의 장점도 일부 수용하였기에 C#은 자바보다 표현 능력은 약간 낫다고 할 수 있다. C#에는 있지만 자바에는 없는 기능으로는 C++의 function pointer의 객체 버전이라 할 수 있는 delegate, 멤버 변수이외에 별도의 Property 둔 것, delegate 기반의 Event, indexer 등을 들 수 있다. C#의 Interface는 자바의 Interface와 달리 위에서 언급한 property, event, indexer 등을 선언할 수 있다. 또한 이글에서 말하고자하는 아주 작지만 재밌는 차이도 있다. 예전에 유익하게 읽었던 Effective Java 기억에 Effective C#을 읽다가 의심이 나서 테스트를 하게 되었다.

// C#
  interface IMsg
  {
    void Message();
  }
  class Parent : IMsg
  {
    public void Message()
    {
      Console.WriteLine("부모가 불렸네.");
    }
  }
  class Child : Parent
  {
    public new void Message()
    {
      Console.WriteLine("자식이 불렸네.");
    }
  }

// Java
public interface IMsg
{
  void Message();
}
public class Parent implements IMsg
{
  public void Message()
  {
    System.out.println("부모가 불렸네.");
  }
}
public class Child extends Parent
{
  public void Message()
  {
    System.out.println("자식이 불렸네.");
  }
}

두 언어 중 하나만 아는 사람이 봐도 위 코드는 같게 구현되어 있음을 알 수 있다. 이 경우 아래와 같은 코드에 의해 찍히는 값은 어떻게 될까 ?
  IMsg message = new Child();
  message.Message();

C#의 경우는 "부모가 불렸네", Java의 경우 "자식이 불렸네." 이다.
Effective C# (빌와그너 저, 김명신 역)는 이렇게 적고 있다. C#에서 Inferface의 구현은 virtual 메소드의 overriding과는 전혀 다른 것이며, Interface는 그것을 구현한 클래스를 바라보는 제한된 창이며 계약이다.
Java와 같은 결과를 얻으려면 어떻게 할까 ?
우선, Child 클래스의 선언시 Interface를 구현하는 것으로 지정한다. 즉,
class Child : Parent, IMsg
자바와 마찬가지로 C#도 클래스의 단일 상속, 인터페이스의 복수 상속을 규정하고 있다.

혹은 다음과 같은 Parent 클래스의 IMsg 구현시 메소드를 virtual로 선언하고 Child에서 override하면 된다.
class Parent : IMsg
{
  public virtual void Message()
  {
class Child : Parent
{
  public override void Message()
  {

이 테스트에서 추론할 수 있는 것은 자바의 경우 Interface의 구현과, 상속을 통한 polymorphism이 동일하게 동작하는 듯 하며, C#은 이를 분명히 구분하고 있다.

Posted by 장현춘

댓글을 달아 주세요