2010-12-17 5 views
11

인터페이스에 대한 특정 쿼리가 하나 있습니다. 기본적으로 인터페이스 메소드는 추상과 가상입니다. 따라서 인터페이스를 구현하고 클래스에서 정의를 제공하면 실제로 메소드를 오버라이드하지만 메소드를 구현 클래스에서 다시 가상으로 표시하면 컴파일러가 실제로 시도하는 것을 고려하지 않은 이유는 무엇입니까? 원래 인터페이스 가상 메서드를 숨길 수 있습니다. 기본 클래스에 가상 메서드가 있고 파생 클래스가 메서드를 가상으로 다시 표시하면 컴파일러에서 기본 클래스 메서드를 숨기고 있다는 경고를 표시하므로 의도적으로 새로운 메서드를 사용하십시오. 기본 클래스 메서드를 숨 깁니다. 당신이이 같은 코드를 볼 수 ILDASM의 인터페이스와 개방에 대한 위의 코드를 작성하는 경우인터페이스 메소드를 구현하는 동안 virtual이 허용되는 이유는 무엇입니까?

public interface ITestInterface 
{ 
void virtualmethod(); // this method is by default virtual. 
} 

public class TestInterface :ITestInterface 
{ 
public virtual void virtualmethod() 
{ 
// Now compiler should consider that i am actually hiding the interface virtual method. 
} 
} 

: 인터페이스에서 구현 .method public hidebysig newslot abstract virtual instance void virtualmethod() cil managed { }//end of method ITestInterface::virtualmethod

+2

가상의 인터페이스 대신 인터페이스의 메소드가 기본적으로 추상이라고 가정하면보다 의미가 있습니다. –

+0

네, 괜찮습니다.하지만 일단 컴파일러가 메소드에 가상을 첨부하면 메서드를 구현하는 동안 다시 가상을가집니다. 그러면 컴파일러는 원래 선언을 숨기고 있다고 말해야합니다. –

답변

39

방법을 기본적으로 하지 가상 있습니다. 인터페이스 정의에 정의 된 계약의 구현을 제공하는 것일뿐입니다. 메서드를 virtual으로 표시하면 정의 된대로 계약을 계속 준수하면서 파생 클래스가 추가 또는 개별 구현을 제공 할 수 있습니다.

interface IAnimal 
{ 
    string Speak(); 
} 

class Dog : IAnimal 
{ 
    public string Speak() 
    { 
     return "Bark!"; 
    } 
} 

Dog 클래스 계약 IAnimal의 구현을 제공함으로써 인터페이스를 구현 :

이 예를 생각해 보자. 여기에는 가상 메서드가없고 우선 적용되지 않습니다.
interface IAnimal 
{ 
    string Speak(); 
} 

class Dog : IAnimal 
{ 
    public virtual string Speak() 
    { 
     return "Bark!"; 
    } 
} 

class GoldenRetriever : Dog 
{ 
    public override string Speak() 
    { 
     return "I am a golden retriever who says " 
        + base.Speak(); 
    } 
} 

는 이제 Dog 클래스를 추가하거나 새로운 구현을 제공하는 파생 클래스 허용 virtualSpeak을 선언했다 :

지금이 예제를 고려하십시오. Speak 메서드를 호출해도 여전히 문자열이 반환되므로 IAnimal으로 계약을 위반하지 않습니다.

네, 마지막 예. 인터페이스는 구현을 필요로하지 않는다는 것을 기억하십시오 - 계약 만 만족하면됩니다. 즉, 인터페이스는 구현 클래스에 일치하는 서명이있는 멤버 만 존재한다는 것을 의미합니다. 이것은 우리가 또한이 작업을 수행 할 수 있음을 의미 :

interface IAnimal 
{ 
    string Speak(); 
} 

abstract class Dog : IAnimal 
{ 
    public abstract string Speak(); 
} 

class GoldenRetriever : Dog 
{ 
    public override string Speak() 
    { 
     return "I am a golden retriever"; 
    } 
} 

공지 사항 지금 Dog 클래스는 모든 Speak에 대한 구현을 제공하지 않는다는 점 아직 계약의 요구 사항을 만족하고있다.

인터페이스도 클래스에서 클래스로 상속되므로 위의 모든 예제에서 DogGoldenRetriever은 모두 IAnimal 인터페이스를 구현합니다. 어떤 클래스도 Speak 메서드를 숨 깁니다. 두 클래스 모두 입니다.


사실, 가상 클래스가 클래스가 아니라 인터페이스에 정의되어 있다는 혼란이있을 수 있습니다.여기에 내가 위에서 정의 된 인터페이스의 IL은 다음과 같습니다

.class private interface abstract auto ansi IAnimal 
{ 
    .method public hidebysig newslot abstract 
     virtual instance string Speak() cil managed 
    { 
    } 
} 

당신이 여기 유형은 interface로 지정된 것을 알 필요가 virtual 같은 방법이 정의되어 있는지 정확하지만. 이것은 순수하게 Microsoft의 C# 컴파일러에서 생성 된 MSIL의 구현 세부 사항입니다. 다른 컴파일러는 의미 론적으로 동일한 결과를 제공하는 한 다른 코드를 쉽게 생성 할 수있었습니다.

여기서 중요한 것은 인터페이스에 virtual이라는 메서드가 선언되어 있어도 클래스에 선언 된 virtual 메서드와 동일한 것을 의미하지는 않습니다.

+0

똑같은 일리노이 코드를 추가하면 문제가 다시 확인됩니다. –

+0

.method public hidebysig newslot 추상 가상 인스턴스 void virtualmethod() cil managed {} // 메서드의 끝 ITestInterface :: virtualmethod –

2

인터페이스는 기본 클래스가 아니므로 구현 방법이 재정의되지 않습니다. 인터페이스는 메서드 만 선언합니다. 인터페이스 메서드는 기본적으로 가상이 아니며 infact 인터페이스는 해당 인터페이스를 구현하는 클래스에서 사용할 수있는 메서드 만 선언합니다.

가상으로 선언 할 수 없습니다.

구현자가 구현 자의 논리에 완전히 의존하는 가상화가 가능하거나 불가능할 수 있습니다.

+0

인터페이스는 가상 그래서 행동은 클래스와 같아야한다. –

+1

@Mohit - 이것은 완전히 사실이 아닙니다. 그렇습니다. 그것들은 단지 또 다른 유형이지만 그들은 모든 차이를 만드는 * 인터페이스 * 유형입니다. 인터페이스와 클래스는 IL 수준에서 다릅니다. –

관련 문제