문제

에서 제시티의 프로그래밍 C#(p.142)그는 예를 제공합니다 어디 그를 캐스팅하는 개체는 인터페이스입니다.

 interface IStorable
 {
    ...
 }

 public class Document : IStorable
 {
    ...
 }

 ...
 IStorable isDoc = (IStorable) doc;  
 ...

무엇이 포인트이,특히 경우 객체의 클래스를 구현하모버젼은 작동까요?

EDIT1:을 명확히 나에게 관심에 이유에 대한 캐스팅(있을 경우), 이유를 구현하기 위한 인터페이스가 있습니다.또한,이 책은 자신의 2001 년 첫 번째 에디션(based on C#1 그러므로 예되지 않을 수 있습과 밀접한 관련 이후 버전에 대한의 C#).

EDIT2:추가 어떤 상황에 맞는 코드

도움이 되었습니까?

해결책

실제로 캐스트가 필요할 때의 이유는 하나뿐입니다. Doc이 기본 유형의 실제 객체 일 때 istorable을 구현하는 경우. 설명하겠습니다 :

public class DocBase
{
  public virtual void DoSomething()
  {

  }
}

public class Document : DocBase, IStorable
{
  public override void DoSomething()
  {
    // Some implementation
    base.DoSomething();
  }

  #region IStorable Members

  public void Store()
  {
    // Implement this one aswell..
    throw new NotImplementedException();
  }

  #endregion
}

public class Program
{
  static void Main()
  {
    DocBase doc = new Document();
    // Now you will need a cast to reach IStorable members
    IStorable storable = (IStorable)doc;
  }
}

public interface IStorable
{
  void Store();
}

다른 팁

인터페이스에서 제공하는 방법으로만 자신을 제한하고 싶기 때문입니다. 클래스를 사용하는 경우 인터페이스의 일부가 아닌 메소드 (실수로)를 호출 할 위험이 있습니다.

객체가 인터페이스를 명시 적으로 구현하는 경우 (public void IStorable.StoreThis(...)) 그 캐스팅은 실제로 인터페이스 멤버에 도달하는 가장 쉬운 방법입니다.

나는이 책에서 어떤 맥락이 그 예를 제시했는지 잘 모르겠습니다. 그러나 일반적으로 여러 상속을 달성하기 위해 객체를 인터페이스에 입력 할 수 있습니다. 아래의 예를 제시했습니다.

public interface IFoo
{
     void Display();
}
public interface IBar
{
     void Display();
}

public class MyClass : IFoo, IBar
{
    void IBar.Display()
    {
        Console.WriteLine("IBar implementation");
    }
    void IFoo.Display()
    {
        Console.WriteLine("IFoo implementation");
    }
}

public static void Main()
{
    MyClass c = new MyClass();
    IBar b = c as IBar;
    IFoo f = c as IFoo;
    b.Display();
    f.Display();
    Console.ReadLine();
}

이것은 표시됩니다

IBAR 구현
IFOO 구현

더 많은 맥락 없이는 말하기가 매우 어렵습니다. 변수 인 경우 doc 인터페이스를 구현하는 유형으로 선언되면 캐스트가 중복됩니다.

어떤 버전의 책을 읽고 있습니까? "프로그래밍 C# 3.0"이라면 오늘 밤 집에있을 때 살펴 보겠습니다.

편집 : 지금까지 답변에서 보았 듯이 여기에는 세 가지 잠재적 인 질문이 있습니다.

  • 왜 질문에 표시된 진술에서 캐스팅됩니까? (답 : 당신은 할 필요가 없습니다 doc 적절한 컴파일 타임 유형)
  • 구현 된 인터페이스 또는 기본 클래스에 명시 적으로 캐스트하는 것이 왜 적합합니까? (답 : 다른 답변에 표시된 명시 적 인터페이스 구현, 그리고 캐스트 값을 인수로 전달할 때 덜 구체적인 과부하를 선택하기 위해.)
  • 왜 인터페이스를 사용합니까? (답 : 인터페이스 유형으로 작업하면 나중에 콘크리트 유형의 변화가 덜 취약하다는 것을 의미합니다.)

그만큼 doc 객체는 회원을 구현하는 유형 일 수 있습니다. IStorable 명시 적으로, 1 차 인터페이스 클래스에 추가하지 않는다 (즉, 인터페이스를 통해서만 호출 할 수 있음).

실제로 "캐스팅"((t) 구문 사용)는 C#을 핸들링하기 때문에 (예 : F#와 달리) 자동으로 업 캐스트 (캐스트로 캐스트)를 처리하므로 의미가 없습니다.

여기에는 좋은 답변이 많이 있지만 실제로 가장 제한적인 인터페이스를 실제로 사용하고 싶은 이유는 아니라고 생각합니다.

그 이유는 초기 코딩과 관련이 없으며 다음에 코드를 방문하거나 리팩터링 할 때 또는 다른 사람이 할 때 포함됩니다.

버튼을 원하고 화면에 배치한다고 가정 해 봅시다. 버튼이 전달되거나 다른 기능에서 다음과 같은 버튼을 가져오고 있습니다.

Button x=otherObject.getVisibleThingy();
frame.add(x);

Visiblethingy가 버튼이라는 것을 알게됩니다. 버튼을 반환하므로 모든 것이 차가워집니다 (캐스트 필요 없음).

이제 대신 토글 버튼을 반환하기 위해 visiblethingy를 리팩터링한다고 가정 해 봅시다. 구현에 대해 너무 많이 알고 있으므로 이제 방법을 리팩터링해야합니다.

구성 요소 (버튼과 토글의 부모, 인터페이스 일 수있는 모습의 부모-우리 목적을 위해 거의 모든 것이)에만 필요한 방법이 필요합니다.

Component x=(Component)otherObject.getVisibleThingy();

당신은 아무것도 리팩터링 할 필요가 없었을 것입니다. 방금 작동했을 것입니다.

이것은 매우 간단한 경우이지만 훨씬 더 복잡 할 수 있습니다.

따라서 요약은 인터페이스가 필터를 통해 보는 것과 같은 객체를 "보기"하는 특정 방법이라고 생각합니다. 일부 부품 만 볼 수 있습니다. 당신이 당신의 견해를 충분히 제한 할 수 있다면, 객체는 당신의 특정 관점 뒤에 "변형"할 수 있으며 현재 세계의 어떤 것도 영향을 미치지 않을 수 있습니다. 즉, 매우 강력한 추상화 속임수입니다.

인터페이스에 캐스트하는 가장 좋은 이유는 객체에 대한 코드를 작성하고 그들이 어떤 구체적인 유형인지 알지 못하고 원하지 않는 경우입니다.

특정 인터페이스를 구현하는 객체를 발견 할 수 있다는 것을 알고 있다면이 객체의 콘크리트 클래스를 알지 못하고 객체에서 값을 얻을 수 있습니다. 또한 객체가 주어진 인터페이스를 구현한다는 것을 알고 있다면 해당 인터페이스는 객체에서 특정 작업을 수행하기 위해 실행할 수있는 메소드를 정의 할 수 있습니다.

간단한 예는 다음과 같습니다.

public interface IText
{
   string Text { get; }
}

public interface ISuperDooper
{
   string WhyAmISuperDooper { get; }
}

public class Control
{
   public int ID { get; set; }
}

public class TextControl : Control, IText
{
   public string Text { get; set; }
}

public class AnotherTextControl : Control, IText
{
   public string Text { get; set; }
}

public class SuperDooperControl : Control, ISuperDooper
{
   public string WhyAmISuperDooper { get; set; }
}

public class TestProgram
{
   static void Main(string[] args)
   {
      List<Control> controls = new List<Control>
               {
                   new TextControl
                       {
                           ID = 1, 
                           Text = "I'm a text control"
                       },
                   new AnotherTextControl
                       {
                           ID = 2, 
                           Text = "I'm another text control"
                       },
                   new SuperDooperControl
                       {
                           ID = 3, 
                           WhyAmISuperDooper = "Just Because"
                       }
               };

       DoSomething(controls);
   }

   static void DoSomething(List<Control> controls)
   {
      foreach(Control control in controls)
      {
         // write out the ID of the control
         Console.WriteLine("ID: {0}", control.ID);

         // if this control is a Text control, get the text value from it.
         if (control is IText)
            Console.WriteLine("Text: {0}", ((IText)control).Text);

         // if this control is a SuperDooperControl control, get why
         if (control is ISuperDooper)
            Console.WriteLine("Text: {0}", 
                ((ISuperDooper)control).WhyAmISuperDooper);
      }
   }
}

이 작은 프로그램을 실행하면 다음과 같은 출력이 제공됩니다.

ID : 1

텍스트 : 저는 텍스트 제어입니다

ID : 2

텍스트 : 저는 또 다른 텍스트 컨트롤입니다

ID : 3

텍스트 : 그냥

콘크리트 객체 유형으로 작업 한 모든 객체에 대해 아무것도 알아야하는 DoMething Method에서 코드를 작성할 필요가 없었습니다. 내가 아는 유일한 것은 내가 제어 클래스의 인스턴스 인 객체를 작업한다는 것입니다. 그런 다음 인터페이스를 사용하여 다른 것을 찾을 수 있습니다.

객체의 인터페이스를 사용 하여이 접근 방식을 취하는 백만 가지 이유가 있지만 정확히 무엇이 있는지 정확히 알지 못하고 객체에 액세스 할 수있는 느슨한 방법을 제공합니다.

세계의 모든 신용 카드를 생각해보십시오. 모든 회사는 자체적으로 만들어지고 인터페이스는 동일하므로 모든 카드 리더는 표준을 따르는 카드를 통해 카드를 스 와이프 할 수 있습니다. 인터페이스 사용과 유사합니다.

언급 된 바와 같이, 캐스팅은 불필요하며 필요하지 않습니다. 그러나 그것은 초보자들이 그들의 이해를 돕는 데 유용한 더 명백한 코딩 형태입니다.

입문 교과서에서, 불만 제가 신뢰할 수있는 일을 암시 적으로 수행하게하기보다는 명시 적으로 행동하는 것이 가장 좋습니다. 이는 초보자에게 더 혼란 스러울 것입니다.

"Doc"은 유형의 유형이 아니기 때문에 초보자가 ISDOC에 할당되고 있음을 알게 될 것입니다. 저자 (책과 코드의)는 명시 적으로 캐스팅함으로써 문서가 istorable 객체에 캐스팅 될 수 있지만 istorable 객체와 동일하지 않다고 말합니다.

요점은, 대상 (어디서 얻었습니까?) 5 월 ~ 아니다 인터페이스를 구현하고,이 경우 예외가 발생하여 잡을 수 있습니다. 물론 "IS"연산자를 사용하여 확인할 수 있으며 C 스타일 캐스트 대신 캐스트를하는 "AS"연산자를 사용할 수 있습니다.

을 허용하는 가장 간 분리 코드 조각...

다음과 같은 문서에 대한 더 많은:인터페이스

라이센스 : CC-BY-SA ~와 함께 속성
제휴하지 않습니다 StackOverflow
scroll top