2010-01-22 2 views
186

예를 들어 ICar 인터페이스가 필요하고 모든 구현에 Year 필드가 포함되어 있다고 가정 해 보겠습니다. 이것은 모든 구현이 별도로 Year을 선언해야한다는 것을 의미합니까? 단순히 인터페이스에서 이것을 정의하는 것이 더 좋지 않을까요?C# 인터페이스에 필드가없는 이유는 무엇입니까?

+18

인터페이스에는 구현이 없습니다.이 클래스는 속성을 가진 추상 클래스를 사용합니다. – PostMan

+5

여기에 추가 된 내용은 인터페이스가 계약이고 필드는 시스템 메모리의 슬롯을 정의한다는 구현 세부 사항입니다 값 (스칼라 또는 주소 포인터)을 입력합니다. – herzmeister

+3

필드가 공개이면 계약의 일부이며 구현 세부 사항이 아닌가? – Alex

답변

198

다른 많은 대답이 의미 론적 수준에서 정확하지만 구현 세부 수준에서 이러한 종류의 질문에 접근하는 것도 흥미로운 일입니다.

인터페이스

는 방법을 포함 슬롯의 집합으로 간주 될 수있다. 클래스가 인터페이스를 구현할 때 클래스는 런타임에 필요한 모든 슬롯을 채우는 방법을 알려야합니다. 당신이

interface IFoo { void M(); } 
class Foo : IFoo { public void M() { ... } } 

을 말할 때 클래스 당신이 날의 인스턴스를 만들 때 전화를 할 때, IFoo.M.

다음

의 슬롯에 Foo.M에 대한 참조를 물건 "라고 :

IFoo ifoo = new Foo(); 
ifoo.M(); 

컴파일러는 "개체에 IFoo.M의 슬롯에 어떤 메서드가 있는지 묻고 해당 메서드를 호출합니다.

인터페이스가 메소드를 포함하는 슬롯 모음 인 경우 해당 슬롯 중 일부는 속성의 get 및 set 메서드, 인덱서의 get 및 set 메서드, 및 메서드의 추가 및 제거 메서드를 포함 할 수 있습니다. 행사. 그러나 필드는 방법이 아닙니다. 필드와 연결된 "슬롯"이 없으므로 필드 위치에 대한 참조로 "채울"수 있습니다. 따라서 인터페이스는 메서드, 속성, 인덱서 및 이벤트를 정의 할 수 있지만 필드는 정의 할 수 없습니다.

+21

내가 때때로 그리워하는 한 가지는 인터페이스 수준의 상수를 정의하는 자바와 비슷한 기능입니다.이 기능은 아마도 언어에서 지원하기 위해 "슬롯"을 필요로하지 않을 것입니다. – LBushkin

+2

나는 간단한 단어로 설명을 좋아한다. 감사. "CLR via C#"및 "Essential .net volume 1"은 자세한 내용을 제공합니다. –

+4

필드에 슬롯이없는 이유는 무엇입니까? 그리고 운영자와 같은 질문? 클래스가 인터페이스를 상속받지 않아도 인터페이스가 구현되었는지 확인하기 위해 리플렉션을 사용하여 오리 타이핑에 대해 들었던 것을 기억합니다. 필드를 위로 올리는 데 경사 반사 (또는 슬롯)를 사용하는 이유는 무엇입니까? 나는 필드를 필요로하지 않을 수도 있고 싶을 수도 있기 때문에 코드를 작성하고 있지만 연산자를 사용할 수 없다는 사실을 알고 놀랐습니다. 연산자는 완전히 오버로드 될 수 있다는 것을 제외하고는 (인터페이스는 상수, 필드, 연산자를 포함 할 수 없다는 것만 제외하면) 내 이해에서와 같은 방법입니다 .http : //msdn.microsoft.com/ko-kr/library/ms173156.aspx (영문 일 수 있음) –

40

속성으로 선언 :

interface ICar { 
    int Year { get; set; } 
} 
+36

질문은 "** C# 인터페이스가 필드를 포함 할 수없는 이유는 무엇입니까?"입니다. 이것으로는 해결되지 않습니다. – AakashM

+3

이 답변은 OP 질문에 대답하지 않지만, 잘, 내 문제를 해결 동의합니다. – Gorgen

18

왜 그냥 완벽하게 잘하는 Year 속성을 가지고 있지?

필드는 필드를 포함하지 않으므로 필드는 데이터 표현의 특정 구현을 나타내고 캡슐화가 중단 될 수 있습니다. 따라서 필드와의 인터페이스를 갖는 것은 인터페이스 대신 구현에 대한 코딩 일 것입니다. 이는 인터페이스가 갖는 궁금한 역설입니다!

예를 들어

, 당신의 Year 사양의 일부는 ICar 구현이 말할 수있는 방법은 없습니다 1 또는 1900 년 전에 올해는 노출했다 + 현재의 경우보다 이후 인 Year에 할당을 허용하는 것이 잘못된 것이 필요할 수 있습니다 Year 필드 - 대신 여기에서 작업을 수행하는 대신 속성을 사용하는 것이 좋습니다.

0

이렇게하려면 연도 필드를 구현하는 Car 기본 클래스를 가질 수 있으며 다른 모든 구현은이 클래스의 상속을받을 수 있습니다.

109

C#의 인터페이스는 특정 구현이 아닌 클래스가 준수 할 계약을 정의하기위한 것입니다. 그 정신

, 속성을 정의 할 수 있도록 할 C#을 인터페이스 - 호출 측에 대한 구현을 제공하지해야합니다 자동 속성을 사용할 수 있습니다

interface ICar 
{ 
    int Year { get; set; } 
} 

구현 클래스가 구현을 단순화하기 위해, 어떤이 있다면 속성과 관련된 특수 로직 :

class Automobile : ICar 
{ 
    public int Year { get; set; } // automatically implemented 
} 
+2

공개 된 모든 것이 계약의 일부가 아닙니다. 클래스에 public int Year가있는 경우 클래스 계약에 Year라는 필드가 있고 액세스 할 수 있다고는하지 않습니까? –

+0

파티에 늦기는하지만 아니요,이 경우 계약서에 준수하는 클래스가 구현해야하는 PROPERTY Year가 있음을 의미합니다. 속성은 실제로 get/set 메서드이며, 특별한 논리가 필요하지 않으면 자동으로 생성되는 배킹 필드가 있습니다. 특수 구문은 명확한 표기법입니다. – user3613916

+0

'Year'의 자동 구현에 대한 상수 기본값 (예 : 123)을 어떻게 정의 할 수 있습니까? – lama12345

13

짧은 답변은 모든 구현 유형이 자체 백업 변수를 만들어야합니다. 이는 인터페이스가 계약과 유사하기 때문입니다. 구현 유형에서 사용할 수 있도록 공개적으로 액세스 할 수있는 특정 코드를 지정하면됩니다. 어떤 코드 자체도 포함 할 수 없습니다.

당신이 제안하는 무엇을 사용하여이 시나리오를 고려

public interface InterfaceOne 
{ 
    int myBackingVariable; 

    int MyProperty { get { return myBackingVariable; } } 
} 

public interface InterfaceTwo 
{ 
    int myBackingVariable; 

    int MyProperty { get { return myBackingVariable; } } 
} 

public class MyClass : InterfaceOne, InterfaceTwo { } 

우리는 여기에 문제의 몇 가지있다 : 인터페이스의 모든 구성원이기 때문에

  • 을 - 정의 - 공공, 우리의지지 변수가 이제 인터페이스를 사용하는 모든 사람에게 노출됩니다.
  • 어느 myBackingVariableMyClass일까요?

가장 일반적인 접근 방법은 인터페이스와이를 구현하는 베어 본 추상 클래스를 선언하는 것입니다. 이것에 의해, abstract 클래스로부터 상속 해 자유롭게 구현을 취득하거나 명시 적으로 인터페이스를 구현해, 다른 클래스로부터 상속하는 것이 가능한 유연성을 얻을 수 있습니다.다음과 같이 작동합니다.

3

인터페이스에는 구현이 포함되어 있지 않습니다.

  1. 속성이있는 인터페이스를 정의하십시오.
  2. 더 나아가 해당 클래스를 모든 클래스에서 구현하고이 클래스를 계속 사용할 수 있습니다.
  3. 필요한 경우이 속성을 클래스에서 가상으로 정의하여 해당 동작을 수정할 수 있습니다.
0

인터페이스는 공용 인스턴스 속성 및 메서드를 정의합니다. 필드는 일반적으로 비공개 또는 가장 보호 된, 내부 또는 보호 된 내부에 있습니다 ("필드"라는 용어는 일반적으로 공용으로 사용되지 않음).

다른 응답에서 설명한 것처럼 기본 클래스를 정의하고 모든 상속자가 액세스 할 수있는 보호 된 속성을 정의 할 수 있습니다.

하나의 기이 한 사실은 인터페이스가 실제로 내부으로 정의 될 수 있지만 인터페이스의 유용성을 제한하며 일반적으로 다른 외부 코드에서 사용되지 않는 내부 기능을 정의하는 데 사용됩니다.

32

에릭 리 퍼트 (Eric Lippert)가 말했듯이, 나는 그가 말한 것을 다른 방식으로 사용할 것이다. 인터페이스의 모든 멤버는 가상이며 인터페이스를 상속하는 클래스에 의해 모두 재정의되어야합니다. 인터페이스 선언에 virtual 키워드를 명시 적으로 작성하지 않고 클래스의 override 키워드를 사용하지도 않습니다.

virtual 키워드는 메서드 포인터와 메서드 포인터의 배열 인 메서드 및 메서드로 .NET에 구현됩니다. override 키워드는 v 테이블 슬롯을 다른 메소드 포인터로 채우고 기본 클래스에서 생성 된 포인터를 덮어 씁니다.속성, 이벤트 및 인덱서는 메소드 내부의 메소드로 구현됩니다. 그러나 들판은 그렇지 않습니다. 따라서 인터페이스에는 필드가 포함될 수 없습니다.

+0

Eric에서 언급 한 슬롯 개념에 기술/실제 이름 (v 테이블)을 제공했습니다. 한스 감사합니다. – RBT

5

다른 사람들은 '왜'를 부여 했으므로 인터페이스에 컨트롤을 정의 할 수 있다고 추가합니다. 재산에 포장하는 경우 :

public interface IView { 
    Control Year { get; } 
} 


public Form : IView { 
    public Control Year { get { return uxYear; } } //numeric text box or whatever 
} 
2

많은 이야기가 이미 있지만, 간단하게하기 위해, 여기 내 걸릴 것입니다. 인터페이스는 소비자 또는 클래스에 의해 구현되고 값을 저장할 필드가없는 메소드 계약을 갖기위한 것입니다.

왜 속성이 허용되는지에 대해 논할 수 있습니다. 그래서 간단한 대답은 - 속성은 내부적으로 메서드로만 정의됩니다.

+1

회원에게 액세스해야하는 경우 해당 회원을 등록하면 도움이됩니다. – Unome

관련 문제