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#은 이를 분명히 구분하고 있다.
TAG polymorphism


