문제

할 수 있는 사람이 있었을 쉽게 설명해 주시기 바랍에 대한 인터페이스 나를 또는 지점을 몇 가지 좋은 예를 들어 주십시오.이 인터페이스는 팝업이 여기에 있었지만,나는 지금까지 진출하는 좋은 설명의 인터페이스 또는 그들을 사용하는 경우.

나는 이야기에 대해 인터페이스에서의 컨텍스트 인터페이스에 대추상 클래스입니다.

도움이 되었습니까?

해결책

인터페이스를 사용하면 유형 대신 "설명"에 대해 프로그래밍 할 수 있으므로 소프트웨어의 요소를보다 잘 연결할 수 있습니다.

이런 식으로 생각하십시오. 옆에있는 큐브의 누군가와 데이터를 공유하고 싶으므로 플래시 스틱을 꺼내서 복사/붙여 넣기를 원합니다. 당신은 옆집에 걸어 가고 그 남자는 "그 USB인가?"라고 말합니다. 그리고 당신은 예라고 말합니다 - 모든 세트. 플래시 스틱의 크기 나 메이커의 크기는 중요하지 않습니다. 중요한 것은 USB라는 것입니다.

같은 방식으로 인터페이스를 사용하면 개발을 생성 할 수 있습니다. 다른 비유를 사용 - 사실상 페인트 된 자동차를 사용하는 응용 프로그램을 만들고 싶다고 상상해보십시오. 다음과 같은 서명이있을 수 있습니다.

public void Paint(Car car, System.Drawing.Color color)...

고객이 "이제 트럭을 페인트하고 싶다"고 말할 때까지이 작업을 수행 할 수 있습니다.

public void Paint (Vehicle vehicle, System.Drawing.Color color)...

고객이 "이제 집을 페인트하고 싶어요!"라고 말할 때까지 앱이 넓어 질 것입니다. 처음부터 할 수있는 일은 인터페이스를 만들어냅니다.

public interface IPaintable{
   void Paint(System.Drawing.Color color);
}

... 그리고 그것을 당신의 일상에 전달했습니다.

public void Paint(IPaintable item, System.Drawing.Color color){
   item.Paint(color);
}

바라건대 이것은 의미가 있습니다 - 그것은 꽤 단순한 설명이지만 희망적으로 그것의 핵심에 도달합니다.

다른 팁

인터페이스는 클래스와이를 호출하는 코드간에 계약을 설정합니다. 또한 동일한 인터페이스를 구현하지만 다른 작업이나 이벤트를 수행하는 유사한 클래스를 가질 수 있으며 실제로 작업하는 작업을 알 필요가 없습니다. 이것은 예로서 더 의미가있을 수 있으므로 여기서 시도해 보겠습니다.

개, 고양이, 마우스라는 몇 가지 수업이 있다고 가정 해 봅시다. 이 수업 각각은 애완 동물이며 이론적으로는 애완 동물이라는 다른 클래스에서 모두 물려받을 수 있지만 여기에 문제가 있습니다. 애완 동물은 그 자체로 아무것도하지 않습니다. 당신은 가게에 가서 애완 동물을 살 수 없습니다. 당신은 가서 개나 고양이를 살 수 있지만 애완 동물은 추상적 인 개념이며 구체적인 개념입니다.

그래서 당신은 애완 동물이 특정한 일을 할 수 있다는 것을 알고 있습니다. 그들은 잠을 자거나 먹을 수 있습니다. 그래서 당신은 ipet이라는 인터페이스를 정의하면 이와 같은 것 같습니다 (c# syntax).

public interface IPet
{
    void Eat(object food);
    void Sleep(int duration);
}

개, 고양이 및 마우스 수업은 각각 IPET를 구현합니다.

public class Dog : IPet

따라서 이제 각 수업은 자체적으로 먹고 수면을 구현해야합니다. 예, 계약이 있습니다 ... 이제 요점은 무엇입니까?

다음으로 Petstore라는 새 개체를 만들고 싶다고 가정 해 봅시다. 그리고 이것은 매우 좋은 애완 동물이 아니기 때문에 기본적으로 당신에게 임의의 애완 동물을 판매합니다 (그렇습니다. 이것은 이것이 고안된 예임을 알고 있습니다).

public class PetStore
{
     public static IPet GetRandomPet()
     {    
          //Code to return a random Dog, Cat, or Mouse
     } 
}

IPet myNewRandomPet = PetStore.GetRandomPet();
myNewRandomPet.Sleep(10);

문제는 어떤 종류의 애완 동물이 될지 모른다는 것입니다. 인터페이스 덕분에 당신은 그것이 무엇이든 먹고 자게 될 것입니다.

따라서이 대답은 전혀 도움이되지 않았을 수도 있지만 일반적인 아이디어는 인터페이스가 의존성 주입 및 객체를 얻을 수있는 제어의 역전과 같은 깔끔한 작업을 수행 할 수 있다는 것입니다. 그 물체의 콘크리트 유형이 무엇인지 아는 것.

가장 쉬운 대답은 인터페이스가 수업이 할 수있는 일을 정의한다는 것입니다. 수업이 그 행동을 수행 할 수 있다고 말하는 "계약"입니다.

Public Interface IRollOver
    Sub RollOver()
End Interface

Public Class Dog Implements IRollOver
    Public Sub RollOver() Implements IRollOver.RollOver
        Console.WriteLine("Rolling Over!")
    End Sub
End Class

Public Sub Main()
    Dim d as New Dog()
    Dim ro as IRollOver = TryCast(d, IRollOver)
    If ro isNot Nothing Then
        ro.RollOver()
    End If
End Sub

기본적으로, 당신은 개 클래스가 해당 인터페이스를 계속 구현하는 한 항상 롤오버 할 수 있음을 보장합니다. 고양이가 롤오버 ()를 얻는 능력을 얻으면 해당 인터페이스도 구현할 수 있으며 개와 고양이를 롤오버 ()를 요구할 때 균질하게 치료할 수 있습니다 ().

친구의 차를 운전할 때, 당신은 그 방법을 다소 알고 있습니다. 기존의 자동차는 모두 스티어링 휠, 페달 등과 같은 인터페이스가 매우 유사하기 때문입니다. 이 인터페이스를 자동차 제조업체와 운전자 간의 계약으로 생각하십시오. 드라이버 (소프트웨어 용어로 인터페이스의 사용자/클라이언트)로서, 운전할 수 있도록 다른 자동차의 세부 사항을 배울 필요가 없습니다. 예를 들어, 스티어링 휠을 돌리는 것은 자동차 회전. 자동차 제조업체 (소프트웨어 용어로 인터페이스 구현을 제공하는 사람)로서 새 자동차가 무엇을 가져야하는지, 운전자가 추가 교육없이 운전자를 사용할 수 있도록 어떻게 행동 해야하는지 명확한 아이디어를 얻을 수 있습니다. 이 계약은 소프트웨어 디자인의 사람들이 디퍼 커플 링 (제공자의 사용자)이라고 부르는 것입니다. 클라이언트 코드는 특정 구현 대신 인터페이스를 사용하는 측면에서 객체의 세부 사항을 알 필요가 없습니다. 인터페이스 구현.

인터페이스을 줄이는 메커니즘을 결합이 서로 다른 아마도 서로 다른 부분의 시스템입니다.

.NET

  • 인터페이스 정의의 목록입니다 작업 및/또는 속성입니다.
  • 인터페이스 방법을 항상 공개한다.
  • 인터페이스는 그 자체에 있지 않할 수 없습니다.

클래스를 만들 때는 를 구현하는 인터페이스를 제공해야 합는 명시적 또는 암시적 구현 방법과 특성에 의해 정의된 인터페이스입니다.

또한,.넷은 단지 하나의 기업과 인터페이스에 대한 필요성 개체를 노출하는 방법을 다른 개체 없는 알고 있거나 거짓말의 외부 클래스 계층 구조입니다.이것은으로도 알려진 노출하는 행동을 합니다.

는 예제를 조금 더 구체적인:

고려 우리는 많은 DTO s(데이터 전송을 개체)속성이 있는 누구를 위한 업데이트,마지막 때였다.문제는 모든 DTO 는 이 숙박 시설 하지 않기 때문에 항상 관련이 있습니다.

동일한 시간에 우리가 원하는 일반적인 메커니즘을 보장하는 이러한 속성을 설정하는 경우 사용할 수 있을 때 제출하는 워크플로,그러나 워크플로 개체해야한 느슨하게 결합에서 제출한다.즉송 워크플로우 방법이 정말에 대해 알아의 모든 미묘한 각 개체 및 모든 개체가 워크플로를 반드시되지 않은 DTO 개체입니다.

// First pass - not maintainable
void SubmitToWorkflow(object o, User u)
{
  if (o is StreetMap)
  {
     var map = (StreetMap)o;
     map.LastUpdated = DateTime.UtcNow;
     map.UpdatedByUser = u.UserID;
  }
  else if (o is Person)
  {
     var person = (Person)o;
     person.LastUpdated = DateTime.Now; // Whoops .. should be UtcNow
     person.UpdatedByUser = u.UserID;
  }
  // Whoa - very unmaintainable.

위 코드에서 SubmitToWorkflow() 에 대해 알고 있어야 하는 각 개체입니다.또한,코드가 엉망으로 한 대규모는 경우 사용/치,위반 을 반복하지 않는 자신 (건조)원칙적으로 개발자가 필요합니다 기억하는 복사/붙여 넣기를 때마다 변화하는 새로운 객체를 시스템에 추가됩니다.

// Second pass - brittle
void SubmitToWorkflow(object o, User u)
{
  if (o is DTOBase)
  {
     DTOBase dto = (DTOBase)o;
     dto.LastUpdated = DateTime.UtcNow;
     dto.UpdatedByUser = u.UserID;
  }

그것은 약간 좋지만,그것은 여전히 부서지기 쉬운입니다.우리가 원하는 경우를 제출하는 다른 유형의 개체,우리는 여전히 더 필요한 경우에 문이 있습니다.etc.

// Third pass pass - also brittle
void SubmitToWorkflow(DTOBase dto, User u)
{
  dto.LastUpdated = DateTime.UtcNow;
  dto.UpdatedByUser = u.UserID;

그것은 여전히 부서지기 쉬운,그리고 모두 방법을 부과하는 제약 조건 모든 dto 로이 있을 구현하는 이 숙박 시설에는 우리가 지지 않은 보편적으로 적용됩니다.일부 개발자들 유혹 될 수 있습을 할 수도 방법이지만,냄새가 나쁘다.우리가 원하지 않는 클래스 척 그들은 지원 업데이트를 추적하지만하지 않습니다.

인터페이스는,그들은 어떻게 도움이 되나요?

우리가 정의하는 경우에는 아주 간단한 인터페이스::

public interface IUpdateTracked
{
  DateTime LastUpdated { get; set; }
  int UpdatedByUser { get; set; }
}

모든 클래스가 필요한 이 자동적인 업데이트를 추적할 수 있는 인터페이스를 구현하십시오.

public class SomeDTO : IUpdateTracked
{
  // IUpdateTracked implementation as well as other methods for SomeDTO
}

워크플로의 방법을 만들 수 있습니다 더 많은 일반적인 작고 더 많은 유지 관리하며,그것은 작업을 계속할 것이 얼마나 많은 클래스를 구현하는 인터페이스(dto 로거나 그렇지 않으면)기 때문에 그것은 단지 상품으로 인터페이스입니다.

void SubmitToWorkflow(object o, User u)
{
  IUpdateTracked updateTracked = o as IUpdateTracked;
  if (updateTracked != null)
  {
     updateTracked.LastUpdated = DateTime.UtcNow;
     updateTracked.UpdatedByUser = u.UserID;
  }
  // ...
  • 우리는 주의할 수 있다 변화 void SubmitToWorkflow(IUpdateTracked updateTracked, User u) 는 것을 보장형 안전,그러나 그것은 것 같지 않으로 관련 이러한 상황에서.

일부 생산 코드,우리가 사용하는 우리는 코드 생성을 만들 DTO 클래스는 데이터베이스에서 정의합니다.유일한 것이 개발자가 있을 만들 필드에 이름을 올바르게 장식 클래스와 인터페이스입니다.는 만큼 속성이라는 LastUpdated 및 UpdatedByUser,그것은 단지 작동합니다.

어쩌면 당신은 요청 면 어떻게 데이터베이스에는 레거시는 가능할까요? 당신이해야 할 조금 더라다른 훌륭한 기능의 인터페이스입니다 그들은 당신을 허용할 수 있습 다리를 만들 사이의 클래스입니다.

아래 코드에서는 우리는 가상의 LegacyDTO,기존의 개체 데 마찬가지로 명명된 필드가 있습니다.그것을 구현하 IUpdateTracked 인터페이스를 기존만,다르게 이라는 속성입니다.

// Using an interface to bridge properties
public class LegacyDTO : IUpdateTracked
{
    public int LegacyUserID { get; set; }
    public DateTime LastSaved { get; set; }

    public int UpdatedByUser
    {
        get { return LegacyUserID; }
        set { LegacyUserID = value; }
    }
    public DateTime LastUpdated
    {
        get { return LastSaved; }
        set { LastSaved = value; }
    }
}

수도 있습 것 멋진,그러나 그렇지 혼란을 여러 개요?무슨 일이 있는 경우 그 속성이지만,그들은 다른 것을 의미? .NET 당신에게 능력을 명시적으로 인터페이스를 구현하십시오.

이 무엇을 의미하는 것은 IUpdateTracked 속성을 볼 수 있을 때 우리가 사용하여 참조하 IUpdateTracked.참고 방법은 없는 공정에서 선언하고,선언을 포함하는 인터페이스 이름입니다.

// Explicit implementation of an interface
public class YetAnotherObject : IUpdatable
{
    int IUpdatable.UpdatedByUser
    { ... }
    DateTime IUpdatable.LastUpdated
    { ... }

그래서 많은 유연성을 정의하는 방법은 클래스를 구현하는 인터페이스를 제공합 개발자에게 많은 자유를 분리 물체에서 방법을 사용하는니다.인터페이스가 있는 좋은 방법은 휴식을 연결할 수도 있습니다.

더 많은 인터페이스보다 그냥이 있습니다.이것은 그냥 단순한 실제 예제는가 하면 인터페이스를 기반으로 프로그래밍입니다.

앞서 언급했듯이,그리고 다른 대응을 만들 수 있는 방법을 가지고/또는 반환 인터페이스를 참조하기보다는 특정 클래스를 참조합니다.면하는 데 필요한 중복을 찾을 수 있 목록에서,내가 쓸 수 있는 방법을 소요하고 반환합니다 IList (인터페이스를 정의하는 작업이 작업에서 목록)및 나이 제한되지 않습니다 구체적인 컬렉션 클래스입니다.

// Decouples the caller and the code as both
// operate only on IList, and are free to swap
// out the concrete collection.
public IList<T> FindDuplicates( IList<T> list )
{
    var duplicates = new List<T>()
    // TODO - write some code to detect duplicate items
    return duplicates;
}

주의 버전 관리

그것은 공공 인터페이스,당신이 선언 나는 보증 인터페이스 x 다음과 같이! 그리고 일단 당신이 출 코드고 출판 인터페이스,당신은 결코 그것을 변경합니다.곧 소비자의 코드가에 의존하는 인터페이스,당신은 휴식 하지 않으려는 그들의 코드를 분야에서.

이 게시 Haacked 좋은 토론입니다.

인터페이스를 대상 추상(base)클래스

추상 클래스를 제공할 수 있습 구현하는 반면 인터페이스 할 수 없습니다.추상 클래스에있는 몇 가지 방법이 더 유연하게 버전 관리 측면 당신과 같은 지침 NVPI(Non-가상 공용 인터페이스)패턴이다.

그것은 가치가 있는 옵션을 가지고 있는습니다.NET,클래스만 상속할 수 있에서 하나의 클래스,그러나 클래스를 구현할 수 있습으로 많은 인터페이스는 그것으로 좋아한다.

성 주입

빠른 요약은 인터페이스의 종속성을 주입(DI)이의 사용은 인터페이스를 통해 개발자의 코드 작성하는 프로그램에 대한 인터페이스 서비스를 제공합니다.에서 연습할 수 있으로 끝날의 인터페이스와 작은 클래스고,하나의 아이디어는 작은 클래스에는 한 가지만 한 가지는 훨씬 쉽게 코드고 유지합니다.

class AnnualRaiseAdjuster
   : ISalaryAdjuster
{
   AnnualRaiseAdjuster(IPayGradeDetermination payGradeDetermination) { ...  }

   void AdjustSalary(Staff s)
   {
      var payGrade = payGradeDetermination.Determine(s);
      s.Salary = s.Salary * 1.01 + payGrade.Bonus;
   }
}

에 대한 간략한 이익을 다음과 같 위의 조각에서는 등급을 지불 결정은은으로 주입된 연례 올리 조정자.는 방법을 지불하는 등급이 결정되지 않는 실제로 이 클래스입니다.시험할 때,개발자는 모의 지불 등급 판정에 결과를 확인 급여 조절기능으로 원하는.이 테스트는 빠르기 때문에 이 테스트는 테스트 클래스고,지 않습니다.

이것은 디 프라이머만이 있기 전에 전념 도서 주제위 예제는 아주 간단합니다.

이것은 오히려"장"주제,하지만 내게를 넣어보십시오 그것은 간단합니다.

인터페이스-로"그들은 그 이름을"-는 계약입니다.그러나 잊는 단어입니다.

를 이해하는 가장 좋은 방법들을 통해 어떤 종류의 의사 코드 예제입니다.그게 내가 그들을 이해 오랜 시간 전입니다.

가정 응용 프로그램을 가지고 있다는 메시지입니다.메시지를 담고 몇 가지 물건과 같은 주제,텍스트,등등.

그래서 당신이 당신의 쓰 MessageController 을 읽을 데이터베이스에 추출물 및 메시지입니다.그것은 매우 좋은 때까지 당신이 갑자기 들리는 팩시밀도 구현한다.그래서 당신은 지금 읽어야""팩스 프로세스로를 제공하지 않습니다.

이 수 있으로 쉽게 설정 스파게티 코드입니다.그래서 무엇을 대신 MessageController 는 컨트롤 보다는"메시지"만,당신은 그것을 만들과 함께 일할 수 있는 인터페이스 라는 Art(I 은 단지 일반적인 사용이지만,필요하지 않습니다).

귀하의 웃 인터페이스가 포함 몇 가지 기본적인 데이터는 당신 을 확인할 수 있는 메시지를 처리합니다.

그래서를 만들 때 이메일,팩스,침묵 클래스에,당신은 그들을 구현인터페이스Art.

그래서 당신의 MessageController,당신은 방법을 가질 수 있습니다 라는 다음과 같다:

private void ProcessMessage(IMessage oneMessage)
{
    DoSomething();
}

했다면 사용하지 않는 인터페이스,당신이 있어야:

private void ProcessEmail(Email someEmail);
private void ProcessFax(Fax someFax);
etc.

그래서 사용 일반 인터페이스,당신은 확인했는다 방법이 될 수 있 함께 작업하는 경우에 상관없이,그것에는 팩스,이메일은 침묵,etc.

왜 또는 방법?

기 때문에 인터페이스 계약서 을 지정하는 몇 가지 당신 준수(또는 구)하기 위해 사용할 수 있습니다.그것의 생각으로 뱃지.하는 경우 객체를"팩스"이 없 Art 인터페이스는,다음의 방법이다 할 수 없을 것 함께 작동하는 것,그것은 당신에게 잘못된 형식이기 때문에,당신이 통과 Fax 하는 방법이 기대하는 아이메 개체입니다.

당신이 볼까요?

생각의 인터페이스로"하위"의 방법과 속성을 사용할 수있을 것이다, 에도 불구하고 실사 개체의 유형입니다.는 경우 원래의체(팩스,이메일,침묵,etc.)해당 인터페이스를 구현할 수 있습 안전 전달에서는 방법을 필요로하는 인터페이스입니다.

더 많은 마술에 숨겨진할 수 있습니다 던지기 인터페이스로 다시 원래의 개체:

팩스 myFax=(팩스)SomeIMessageThatIReceive;

ArrayList()습니다.NET1.1 했는데 인터페이스라는 명령.이 있는 경우에는 명령(매우"일반적인")할 수 있으로 변환 ArrayList:

ArrayList ar = (ArrayList)SomeIList;

고 있는 수천 개의 샘플을 밖에서 야생입니다.

인터페이스는 다음과 같 ISortable,IComparable,etc., 을 정의하는 방법과 특성을 에 구현한 클래스를 달성하기 위해서는 기능이 있습니다.

을 확장하는 우리의 견본을 사용할 수 있습니다 List<>의 이메일,팩스,침묵을,모두에서 동일한 목록 형식이 있는 경우에 Art,하지만 당신이 그들 모두 함께 경우에는 개체는 단순히 이메일,팩스,등등.

하고 싶은 경우에는 정렬(또는 열거한 예)귀하의 개체,당신은 그들을 필요로 구현하는 해당 인터페이스입니다.니다.NET 샘플는 경우에,당신의 목록을 가지고"팩스"체고할 수 있기를 원 종류 을 사용하여 그들을 MyList.정렬(),당신은 당신 을 팩스 클래스는 다음과 같다:

public class Fax : ISorteable 
{
   //implement the ISorteable stuff here.
}

이 제공합니다.다른 사용자가 가능한 게시물 다른 좋은 예입니다.행운을 빕니다!들의 전력 인터페이스가 있습니다.

경고:지 모든 것에 대한 좋은 인터페이스,거기에 문제,그들과 함께 웁자이 전쟁을 시작합니다.내가 남아 있을 둡니다.하나의 단점의 Interfce(습니다.NET2.0 이상)할 수 없다는 것입니다 개인,회원 또는 보호,그것은 할 수 없습니다.이것은 어떤 의미하지만,때때로 당신은 단순히 선언하는 물건으로 개인 또는 보호됩니다.

기능 인터페이스는 프로그래밍 언어 내에있는 기능 인터페이스 외에도 디자인 아이디어를 다른 사람에게 표현할 때 강력한 의미 론적 도구이기도합니다. 사람들.

잘 설계된 인터페이스가있는 코드베이스는 갑자기 논의하기가 훨씬 쉽습니다. "예, 새로운 원격 서버를 등록하려면 CredentialSmanager가 필요합니다." "작업 인스턴스를 얻으려면 속성 맵을 사물로 전달하십시오."

단일 단어로 복잡한 것을 해결하는 능력은 매우 유용합니다.

인터페이스를 사용하면 일반적인 방식으로 객체에 대한 코드를 코딩 할 수 있습니다. 예를 들어, 보고서를 보내는 방법이 있다고 가정 해보십시오. 이제 새로운 보고서를 작성 해야하는 새로운 요구 사항이 있다고 가정 해 봅시다. 이미 작성한 방법을 재사용 할 수 있다면 좋을까요? 인터페이스는 쉽게 만듭니다.

interface IReport
{
    string RenderReport();
}

class MyNewReport : IReport
{
    public string RenderReport()
    {
        return "Hello World Report!";

    }
}

class AnotherReport : IReport
{
    public string RenderReport()
    {
        return "Another Report!";

    }
}

//This class can process any report that implements IReport!
class ReportEmailer()
{
     public void EmailReport(IReport report)
     {
         Email(report.RenderReport());
     }
}

class MyApp()
{
    void Main()
    {
        //create specific "MyNewReport" report using interface
        IReport newReport = new MyNewReport();

        //create specific "AnotherReport" report using interface
        IReport anotherReport = new AnotherReport();

        ReportEmailer reportEmailer = new ReportEmailer();

        //emailer expects interface
        reportEmailer.EmailReport(newReport);
        reportEmailer.EmailReport(anotherReport);



    }

}

인터페이스는 또한 열쇠 다형성,중 하나는"세 가지의 기둥 OOD".

어떤 사람들은 감동에 위,다형성은 단지 의미어 클래스에 가지고 갈 수 있는 다른"양식".의미가 있는 경우에 우리는 두 개의 클래스,"강아지""고양이"그리고 모두를 구현하는 인터페이스"INeedFreshFoodAndWater"(다)-귀하의 코드는 다음과 같이 할 수 있다(사):

INeedFreshFoodAndWater[] array = new INeedFreshFoodAndWater[];
array.Add(new Dog());
array.Add(new Cat());

foreach(INeedFreshFoodAndWater item in array)
{
   item.Feed();
   item.Water();
}

이것은 강력한할 수 있기 때문에 치료하는 다른 클래스의 객체를 추상적으로 수행 할 수 있도록 같은 것들을 만들의 개체를 더욱 느슨하게 결합니다,등등.

좋아, 그래서 그것은 추상 클래스 대 인터페이스에 관한 것입니다 ...

개념적으로, 추상 클래스는 기본 클래스로 사용됩니다. 종종 그들은 이미 기본적인 기능을 제공하며 서브 클래스는 추상 방법을 자체 구현해야합니다 (이는 추상 기본 클래스에서 구현되지 않은 방법입니다).

인터페이스는 주로 특정 구현의 세부 사항에서 클라이언트 코드를 분리하는 데 사용됩니다. 또한 때로는 클라이언트 코드를 변경하지 않고 구현을 전환 할 수있게되면 클라이언트 코드가 더 일반화됩니다.

기술적 인 수준에서는 일부 언어 (예 : C ++)에서는 구문 차이가 없거나 분리 또는 일반화 목적으로 추상 클래스를 사용할 수 있기 때문에 추상 클래스와 인터페이스 사이에 선을 그리는 것이 더 어렵습니다. 모든 기본 클래스는 정의에 따라 모든 서브 클래스가 명예를 존중 해야하는 인터페이스를 정의하기 때문에 추상 클래스를 인터페이스로 사용하는 것이 가능합니다 (즉, 기본 클래스 대신 서브 클래스를 사용할 수 있어야합니다).

인터페이스는 객체가 상속을 사용할 필요없이 일정량의 기능을 구현하도록 시행하는 방법입니다 (인터페이스를 사용하여 달성 할 수있는 느슨하게 결합되지 않고 강하게 결합 된 코드로 이어집니다).

인터페이스는 구현이 아니라 기능을 설명합니다.

당신이 겪는 대부분의 인터페이스는 방법과 속성 서명 모음입니다. 인터페이스를 구현하는 사람은 인터페이스에있는 것에 대한 정의를 제공해야합니다.

간단히 말해서 : 인터페이스는 메소드가 정의되었지만 구현이없는 클래스입니다. 대조적으로 추상 클래스에는 몇 가지 방법이 구현되었지만 전부는 아닙니다.

인터페이스를 계약으로 생각하십시오. 클래스가 인터페이스를 구현하면 본질적으로 해당 계약의 조건을 존중하는 것이 동의합니다. 소비자로서, 당신은 당신이 가진 물체가 계약 의무를 수행 할 수있는 것을 걱정합니다. 그들의 내부 작업과 세부 사항은 중요하지 않습니다.

Java에서 인터페이스 대 추상 클래스를 사용하는 한 가지 이유 중 하나는 서브 클래스가 여러 기본 클래스를 확장 할 수 없지만 여러 인터페이스를 구현할 수 있기 때문입니다.

Java는 여러 상속을 허용하지 않습니다 (아주 좋은 이유로, 끔찍한 다이아몬드를 찾아보십시오) 수업을 여러 가지 행동 세트를 공급하려면 어떻게해야합니까? 그것을 사용하는 사람은 그것을 직렬화 될 수 있고 화면에 페인트 할 수 있다는 것을 알고 싶다고 가정 해 봅시다. 대답은 두 개의 다른 인터페이스를 구현하는 것입니다.

인터페이스에는 자체 구현이 포함되어 있지 않으며 인스턴스 멤버가 없기 때문에 모호성없이 동일한 클래스에서 몇 가지를 구현하는 것이 안전합니다.

아래쪽은 각 클래스에서 개별적으로 구현해야한다는 것입니다. 따라서 계층 구조가 단순하고 구현의 일부가 모든 상속 클래스에 동일 해야하는 부분이있는 경우 추상 클래스를 사용합니다.

정적으로 유형 된 객체 지향 언어의 인터페이스를 언급한다고 가정하면, 주요 용도는 클래스가 특정 계약 또는 프로토콜을 따른다고 주장하는 것입니다.

당신이 가지고 있다고 말하십시오 :

public interface ICommand
{
    void Execute();
}
public class PrintSomething : ICommand
{
    OutputStream Stream { get; set; }
    String Content {get; set;}
    void Execute()
    { 
        Stream.Write(content);
    }
}

이제 대체 명령 구조가 있습니다. execute를 구현하는 클래스의 인스턴스는 어떤 종류의 목록에 저장 될 수 있으며, ienumerable을 구현하는 것을 말하면 각 객체가 올바른 일을 할 것임을 알면서이를 통해 반복하고 각각을 실행할 수 있습니다. 실행할 명령 목록이있는 CompositeCommand를 구현하여 Composite 명령을 만들 수 있습니다. 또는 일련의 명령을 반복적으로 실행할 루핑 커뮤니케이션이 있으면 대부분의 간단한 통역사가 있습니다.

객체 세트를 모두 공통적으로 가지고있는 동작으로 줄일 수 있다면 인터페이스를 추출 할 수 있습니다. 또한 때로는 인터페이스를 사용하여 객체가 실수로 해당 클래스의 관심사에 대한 침입을 방지 할 수 있습니다. 예를 들어, 클라이언트가 객체의 데이터를 변경하는 대신 검색 할 수있는 인터페이스를 구현할 수 있으며 대부분의 객체가 검색 인터페이스에 대한 참조 만 받게됩니다.

인터페이스는 인터페이스가 비교적 단순하고 가정을 거의 할 때 가장 잘 작동합니다.

Liskov 자산 원칙을 찾아서 더 이해하기 위해 더 이해하십시오.

C ++와 같은 정적으로 유형 된 일부 언어는 일류 개념으로 인터페이스를 지원하지 않으므로 순수한 추상 클래스를 사용하여 인터페이스를 만듭니다.

업데이트추상 클래스 대 인터페이스에 대해 묻는 것처럼 보이므로 여기에 내가 선호하는 지나치게 단순화됩니다.

  • 인터페이스는 기능 및 기능을 정의합니다.
  • 초록 클래스는 핵심 기능을 정의합니다.

일반적으로 추상 클래스를 구축하기 전에 추출 인터페이스 리팩토링을합니다. 창조적 계약이 있어야한다고 생각되면 추상 클래스를 구축 할 가능성이 더 높습니다 (특히 특정 유형의 생성자가 항상 서브 클래스에 의해 지원되어야 함). 그러나 나는 c#/java에서 "순수한"추상 클래스를 거의 사용하지 않습니다. 의미있는 행동이 포함 된 적어도 하나의 방법을 가진 클래스를 구현하고 초록 방법을 사용하여 해당 방법에 의해 불리는 템플릿 메소드를 지원할 가능성이 훨씬 높습니다. 그런 다음 추상 클래스는 동작의 기본 구현이며, 모든 콘크리트 서브 클래스는 되풀이하지 않고도 활용할 수 있습니다.

간단한 답변 : 인터페이스는 많은 메소드 서명 (+ 리턴 유형)입니다. 물체가 말할 때 구현 인터페이스는 해당 메소드 세트를 노출한다는 것을 알고 있습니다.

인터페이스를 구현하는 방법 규칙에서는 방법은 여전히 강하게 입력하고 다형성입니다.

좋은 실제 예는 것 IDisposable 습니다.NET.클래스를 구현하는 IDisposable 인터페이스군이 해당 클래스를 구현하는 폐기()메소드가 있습니다.하드 디스크 드라이브가 구현되지 않았다 Dispose()를 컴파일할 때 오류를 건설하려고 하는 것입니다.또한,이 코드는 패턴:

using (DisposableClass myClass = new DisposableClass())
  {
  // code goes here
  }

원인이됩니다 myClass.폐기()를 실행할 때 자동으로 실행을 종료한 내부 블록입니다.

그러나,이것은 중요가 없다,집행하는 폐기()메소드해야 할 것입니다.할 수 있는 당신의 처분()메소드를 선택 임의의 조리법 파일에서 그들을 이메일 배포 목록 컴파일러는 걱정하지 않는다.의 의도 IDisposable 패턴은 리소스 더 쉽습니다.는 경우 클래스의 인스턴스를 개최한다에 파일을 처리한 다음 IDisposable 매우 쉽게 중앙 집중화 할당 해제하고 정리 코드에서 하나의 스팟을 촉진 스타일의 사용을 보장하는 할당 해제 항상 발생합니다.

그리고 그 핵심 인터페이스가 있습니다.그들은이 방법을 간소화 프로그래밍 규칙 및 디자인 패턴이 있습니다.는 때,올바르게 사용을 촉진하는 간단,자기 문서화하는 코드는 쉽게 사용을 유지 관리하기 쉽고 정확하게 작동합니다.

다음은 자주 사용하는 DB 관련 예입니다. 목록과 같은 객체와 컨테이너 객체가 있다고 가정 해 봅시다. 언젠가 객체를 특정 순서로 저장하고 싶을 수도 있다고 가정 해 봅시다. 시퀀스가 배열의 위치와 관련이 없지만 대신 객체가 더 큰 객체 세트의 서브 세트이고 시퀀스 위치는 데이터베이스 SQL 필터링과 관련이 있다고 가정합니다.

사용자 정의 된 시퀀스 위치를 추적하려면 객체가 사용자 정의 인터페이스를 구현할 수 있습니다. 사용자 정의 인터페이스는 이러한 시퀀스를 유지하는 데 필요한 조직의 노력을 중재 할 수 있습니다.

예를 들어, 관심있는 순서는 레코드의 기본 키와 관련이 없습니다. 객체가 인터페이스를 구현하면 myObject.next () 또는 myObject.prev ()라고 말할 수 있습니다.

나는 당신과 같은 문제를 겪었고 "계약"설명이 약간 혼란 스럽습니다.

메소드가 파라미터 내로 ienumerable 인터페이스를 가져 오도록 지정하면 매개 변수가 ienumerable 인터페이스에서 상속하는 유형이어야하므로 ienumerable 인터페이스에 지정된 모든 메소드를 지원하는 유형이어야한다고 지정할 수 있습니다. 우리가 추상 클래스 나 일반 클래스를 사용하더라도 마찬가지입니다. 해당 클래스에서 상속하는 객체는 매개 변수로 전달해도 괜찮습니다. 어떤 경우에는 상속 된 객체가 기본 클래스가 일반 클래스, 추상 클래스 또는 인터페이스인지 여부에 관계없이 기본 클래스의 모든 공개 메소드를 지원한다고 말할 수 있습니다.

모든 추상 방법을 가진 추상 클래스는 기본적으로 인터페이스와 동일하므로 인터페이스가 단순히 구현 된 메소드가없는 클래스라고 말할 수 있습니다. 실제로 언어에서 인터페이스를 삭제하고 대신 추상 방법 만 사용하여 추상 클래스를 사용할 수 있습니다. 나는 우리가 그것들을 분리하는 이유는 의미 론적 이유 때문이지만 코딩 이유는 그 이유를보고 혼란스러워한다는 것을 알게됩니다.

인터페이스는 클래스의 또 다른 변형이기 때문에 인터페이스 인터페이스 클래스의 인터페이스 이름을 바꾸는 것입니다.

특정 언어에는 클래스가 1 개의 클래스 만 상속받을 수있는 미묘한 차이가 있지만 다른 인터페이스에서는 다른 많은 인터페이스를 가질 수 있지만 다른 문제는 다른 문제이며 직접 관련이있는 것은 아닙니다.

인터페이스를 이해하는 가장 간단한 방법은 클래스 상속이 무엇을 의미하는지 고려하여 시작하는 것입니다. 두 가지 측면이 포함되어 있습니다.

  1. 파생 클래스의 구성원은 기본 클래스의 공개 또는 보호 된 구성원을 자신의 것으로 사용할 수 있습니다.
  2. 파생 클래스의 구성원은 기본 클래스의 구성원을 기대하는 코드로 사용할 수 있습니다 (의미 대체 가능).

이 두 가지 기능은 모두 유용하지만 클래스가 둘 이상의 클래스 멤버를 자체로 사용하기가 어렵 기 때문에 많은 언어와 프레임 워크를 사용하면 클래스가 단일 기본 클래스에서 상속 될 수 있습니다. 반면에, 여러 다른 관련없는 것들에 대해 수업을 대체 할 수있는 특별한 어려움은 없습니다.

또한, 상속의 첫 번째 이점은 캡슐화를 통해 크게 달성 될 수 있기 때문에, 제 1 유형의 다중 상속을 허용함으로써의 상대적 이점은 다소 제한적이다. 반면에, 다수의 관련없는 유형의 사물을 대체 할 수있는 것은 언어 지원 없이는 쉽게 달성 할 수없는 유용한 능력이다.

인터페이스는 언어/프레임 워크가 프로그램이 첫 번째를 제공 할 필요없이 여러 기본 유형에 대한 상속의 두 번째 측면에서 혜택을받을 수있는 수단을 제공합니다.

인터페이스는 완전히 추상적 인 클래스와 같습니다. 즉, 추상 회원 만있는 추상 클래스입니다. 여러 인터페이스를 구현할 수도 있습니다. 이는 여러 개의 추상 클래스에서 상속하는 것과 같습니다. 어쨌든 ..이 설명은 추상 클래스가 무엇인지 이해하는 경우에만 도움이됩니다.

다른 사람들이 여기에서 말했듯이 인터페이스는 계약 (인터페이스를 사용하는 클래스가 "보기")을 정의하고 추상 클래스가 공유 기능을 정의합니다.

코드가 도움이되는지 봅시다.

public interface IReport
{
    void RenderReport(); // This just defines the method prototype
}

public abstract class Reporter
{
    protected void DoSomething()
    {
        // This method is the same for every class that inherits from this class
    }
}

public class ReportViolators : Reporter, IReport
{
    public void RenderReport()
    {
        // Some kind of implementation specific to this class
    }
}

public class ClientApp
{
    var violatorsReport = new ReportViolators();

    // The interface method
    violatorsReport.RenderReport();

    // The abstract class method
    violatorsReport.DoSomething();
}

인터페이스에는 인터페이스에 정의 된 메소드를 포함하도록 구현하는 클래스가 필요합니다.

목적은 클래스에서 코드를 볼 필요없이 특정 작업에 사용할 수 있는지 알 수 있도록하는 것입니다. 예를 들어, Java의 정수 클래스는 비슷한 인터페이스를 구현하므로 메소드 헤더 (public class string emplements 비슷한) 만 보았을 때 비교 () 메소드가 포함되어 있음을 알 수 있습니다.

간단한 경우, 당신은 구현하는 공통 기본 클래스를 사용하여 인터페이스와 비슷한 것을 달성 할 수 있습니다. show() (또는 아마도 그것을 추상적으로 정의 할 수 있습니다). 일반 이름을 더 구체적인 것으로 바꾸겠습니다. 독수리 그리고 대신에 myclass1 그리고 myclass2. 이 경우 코드를 작성할 수 있습니다

Bird bird = GetMeAnInstanceOfABird(someCriteriaForSelectingASpecificKindOfBird);
bird.Fly(Direction.South, Speed.CruisingSpeed);

즉, 처리 할 수있는 코드를 작성할 수 있습니다. a . 그런 다음 원인 코드를 작성할 수 있습니다 인스턴스에 작용하는 일 (비행, 먹고, 알을 낳는 등) . 그 코드는 작동하는지에 관계없이 작동합니다 정말입니다 독수리, , 또는 다른 것 .

그래도 그 패러다임이 지저분 해지 기 시작하지만, 당신이 진실이 없을 때 a 관계. 하늘에서 날아 다니는 코드를 쓰고 싶다고 가정 해 봅시다. 해당 코드를 작성하여 수락하는 경우 기본 클래스, 갑자기 그 코드가 점보 제트 예, a 그리고 a 점보 제트 확실히 둘 다 날 수 있습니다 점보 제트 가장 확실한 것은 아닙니다 .

인터페이스를 입력하십시오.

(그리고 독수리, 그리고 ) 하다 공통적으로 그들이 모두 날 수 있다는 것입니다. 인터페이스에서 대신 위의 코드를 작성하는 경우 나는 난다, 해당 코드는 해당 인터페이스에 구현을 제공하는 것에 적용 할 수 있습니다.

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