program tip

인터페이스, 다중 상속 vs 인터페이스, 인터페이스의 이점을 사용하는 이유는 무엇입니까?

radiobox 2020. 11. 25. 07:49
반응형

인터페이스, 다중 상속 vs 인터페이스, 인터페이스의 이점을 사용하는 이유는 무엇입니까?


나는 이것에 대해 아직도 약간의 혼란이있다. 내가 지금까지 찾은 것은

(이미 여기에서 비슷한 질문을 받았지만 다른 점이 있습니다.)

  1. 인터페이스는 오직 추상 메소드와 최종 필드의 모음입니다.

  2. Java에는 다중 상속이 없습니다.

  3. 인터페이스를 사용하여 Java에서 다중 상속을 수행 할 수 있습니다.

  4. 상속의 강점 중 하나는 파생 클래스에서 기본 클래스의 코드를 다시 작성하지 않고도 사용할 수 있다는 것입니다. 이것이 상속에있어 가장 중요한 일이 될 수 있습니다.

지금..

Q1. 인터페이스에는 추상 메서드 (코드 없음) 만 있기 때문에 인터페이스를 구현하는 경우 상속이라고 어떻게 말할 수 있습니까? 우리는 코드를 사용하지 않습니다.

Q2. 인터페이스 구현이 상속이 아닌 경우 다중 상속을 달성하기 위해 인터페이스를 어떻게 사용합니까?

Q3. 어쨌든 인터페이스 사용의 이점은 무엇입니까? 그들은 코드가 없습니다. 우리는 그것을 구현하는 모든 클래스에서 코드를 반복해서 작성해야합니다.

그렇다면 인터페이스를 만드는 이유는 무엇입니까?

참고 : 인터페이스가 도움이되는 경우를 발견했습니다. 한 가지 예는 Runnable 인터페이스에 스레드의 기능을 정의하는 public void run () 메서드가 있고이 메서드가 별도의 스레드로 실행되는 코딩이 내장되어 있습니다. 그래서 우리는 스레드에서 무엇을해야하는지 코딩 만하면됩니다. Rest는 미리 정의되어 있습니다. 그러나 이것은 추상 클래스 등을 사용하여 달성 할 수도 있습니다.

그렇다면 인터페이스 사용의 정확한 이점은 무엇입니까? 인터페이스를 사용하여 달성 한 것이 실제로 다중 상속입니까?


Q1. 인터페이스에는 추상 메서드 (코드 없음) 만 있기 때문에 인터페이스를 구현하는 경우 상속이라고 어떻게 말할 수 있습니까? 우리는 코드를 사용하지 않습니다.

우리는 할 수 없습니다. 인터페이스는 다중 상속을 달성하는 데 사용되지 않습니다. 약간 덜 강력한 구조이지만 더 안전한 것으로 대체합니다. implements대신 키워드에 유의하십시오 extends.

Q2. 인터페이스 구현이 상속이 아닌 경우 다중 상속을 달성하기 위해 인터페이스를 어떻게 사용합니까?

그렇지 않습니다. 인터페이스를 사용하면 단일 클래스가 여러 " 보기 ", 다른 API 또는 기능을 가질 수 있습니다 . 예를 들면 클래스가 될 수 있습니다 RunnableCallable두 가지 방법을 효과적으로 같은 일을하고있는 동안, 같은 시간에.

Q3. 어쨌든 인터페이스 사용의 이점은 무엇입니까? 그들은 코드가 없습니다. 우리는 그것을 구현하는 모든 클래스에서 코드를 반복해서 작성해야합니다.

인터페이스는 후자가 도입하는 문제가없는 일종의 다중 상속입니다 (예 : Diamond 문제 ).

인터페이스에 대한 사용 사례는 거의 없습니다.

  1. 객체는 효과적으로 두 가지 ID를 갖습니다. a Tank a Vehicle와 a Weapon입니다. Tank전자 또는 후자가 예상 되는 인스턴스 (다형성)를 사용할 수 있습니다. 이것은 실생활에서 거의 발생하지 않으며 실제로 다중 상속이 더 나은 (또는 특성) 유효한 예입니다.

  2. 간단한 책임 : Tank게임에서 개체 의 인스턴스 Runnable는 스레드에서 실행하고 ActionListener마우스 이벤트에 응답하도록 하는 것입니다.

  3. 콜백 인터페이스 : 객체가 주어진 콜백 인터페이스를 구현하는 경우 수명주기 또는 기타 이벤트에 대한 알림을받습니다.

  4. 마커 인터페이스 : 메서드를 추가하지 않고 쉽게 액세스하여 instanceof개체 기능 또는 희망 사항을 검색합니다. Serializable그리고 Cloneable이것의 예입니다.

당신이 찾고있는 것은 (Scala와 같은) 특성이며 불행히도 Java에서는 사용할 수 없습니다.


인터페이스는 최종 정적 필드 및 추상 메서드의 모음입니다 (새로 Java 8에서는 인터페이스에 정적 메서드를 포함하는 지원이 추가됨).

인터페이스는 어떤 작업을 수행해야한다는 것을 알고있는 상황에서 만들어 지지만 수행 방법은 다를 수 있습니다. 즉, 클래스가 특정 방식으로 동작하기 시작하도록 인터페이스를 구현한다고 말할 수 있습니다.

예를 들어 설명하겠습니다. 우리는 모두 동물이 무엇인지 압니다. 사자는 동물, 원숭이는 동물, 코끼리는 동물, 소는 동물 등입니다. 이제 우리는 모든 동물이 무언가를 먹고 잠을 잔다는 것을 압니다. 그러나 각 동물이 무언가를 먹거나 잠을 잘 수있는 방식은 다를 수 있습니다. 사자가 소가 풀을 먹는 다른 동물을 사냥하여 먹는 것처럼. 하지만 둘 다 먹습니다. 그래서 우리는 이와 같은 의사 코드를 가질 수 있습니다.

interface Animal {
    public void eat();
    public void sleep();   
}

class Lion implements Animal {
    public void eat() {
        // Lion's way to eat
    }

    public void sleep(){
         // Lion's way to sleep
    }
}

class Monkey implements Animal {
    public void eat() {
        // Monkey's way to eat
    }

    public void sleep() {
        // Monkey's way to sleep
    }
}

위에서 언급 한 의사 코드에 따라 먹거나 잠을 잘 수있는 모든 것을 동물이라고 부르거나 모든 동물이 먹고자는 것은 필수라고 말할 수 있지만 먹고자는 방법은 동물에 따라 다릅니다.

인터페이스의 경우 클래스 상속의 경우처럼 실제 코드가 아닌 동작 만 상속합니다.

Q1. 인터페이스에는 추상 메서드 (코드 없음) 만 있기 때문에 인터페이스를 구현하는 경우 상속이라고 어떻게 말할 수 있습니까? 우리는 코드를 사용하지 않습니다.

인터페이스 구현은 다른 종류의 상속입니다. 상속 자식 클래스가 기본 클래스에서 재사용 할 실제 코드를 가져 오는 것처럼 클래스 상속과 유사하지 않습니다.

Q2. 인터페이스 구현이 상속이 아닌 경우 다중 상속을 달성하기 위해 인터페이스를 어떻게 사용합니까?

하나의 클래스가 둘 이상의 인터페이스를 구현할 수 있기 때문입니다. 그러나 우리는이 상속이 클래스의 상속과 다르다는 것을 이해해야합니다.

Q3. 어쨌든 인터페이스 사용의 이점은 무엇입니까? 그들은 코드가 없습니다. 우리는 그것을 구현하는 모든 클래스에서 코드를 반복해서 작성해야합니다.

인터페이스를 구현하면 클래스에 모든 추상 메서드를 재정의해야한다는 강박이 발생합니다.

여기여기 내 책 에서 더 많은 것을 읽으 십시오


키스

나는 인터페이스를 이해하기 위해 며칠, 아니 몇 주 동안 검색했고 동일한 일반적인 도움말을 읽는 것 같습니다. 나는 기여를 폄하하려는 것이 아니라 전구가 방금 클릭되었다고 생각하여 엉망입니다 :))

나는 Keep It Simple Stupid를 선호하므로 새로운 인터페이스에 대한 견해를 제시 할 것입니다.

저는 평범한 코더이지만 다른 사람들이 인터페이스를 이해할 수 있도록 VB.NET에서 작성한이 코드를 게시하고 싶습니다 (원칙은 다른 언어에서도 동일 함).

내가 틀렸다면 후속 의견으로 다른 사람들에게 알려주십시오.

설명

폼에있는 세 개의 버튼을 각각 클릭하면 인터페이스 변수 (_data)에 대한 다른 클래스 참조가 저장됩니다. 인터페이스 변수에 대한 다른 클래스 참조의 요점은 중복 된 것처럼 보였기 때문에 이해하지 못한 것입니다. 그러면 그 힘이 msgbox로 분명해집니다. 필요한 작업을 수행하기 위해 SAME 메서드를 호출하기 만하면됩니다. case 'GetData ()'는 현재 인터페이스 참조 변수 (_data)가 보유하고있는 클래스의 메서드를 사용합니다.

그래서 (데이터베이스, 웹 또는 텍스트 파일에서) 내 데이터를 얻고 싶지만 동일한 메서드 이름을 사용하여 수행됩니다 . 그 구현 뒤에있는 코드 ... 나는 신경 쓰지 않는다.

그러면 종속성없이 인터페이스를 사용하여 각 클래스 코드를 쉽게 변경할 수 있습니다. 이것은 OO 및 캡슐화의 핵심 목표입니다.

사용시기

클래스를 코딩하고 'GetData ()'와 같은 메서드에 사용되는 동일한 동사를 발견하면 해당 클래스에 인터페이스를 구현하고 해당 메서드 이름을 추상화 / 인터페이스로 사용하는 것이 좋습니다.

나는 이것이이 어려운 원칙을 가진 동료 멍청이에게 도움이되기를 진심으로 바란다.

Public Class Form1

Private _data As IData = Nothing

Private Sub Button1_Click(ByVal sender As System.Object, ByVal e As System.EventArgs) Handles Button1.Click
    _data = New DataText()
    MsgBox(_data.GetData())
End Sub

Private Sub Button2_Click(ByVal sender As System.Object, ByVal e As System.EventArgs) Handles Button2.Click
    _data = New DataDB()
    MsgBox(_data.GetData())
End Sub

Private Sub Button3_Click(ByVal sender As System.Object, ByVal e As System.EventArgs) Handles Button3.Click
    _data = New DataWeb()
    MsgBox(_data.GetData())
End Sub

End Class

Public Interface IData
Function GetData() As String
End Interface

Friend Class DataText : Implements IData

Friend Function GetData() As String Implements IData.GetData
    Return "DataText"
End Function

End Class

Friend Class DataDB : Implements IData

Friend Function GetData() As String Implements IData.GetData
    Return "DataDB"
End Function

End Class

Friend Class DataWeb : Implements IData

Friend Function GetData() As String Implements IData.GetData
    Return "DataWeb"
End Function

End Class

Q1. 인터페이스에는 추상 메서드 (코드 없음) 만 있기 때문에 인터페이스를 구현하는 경우 상속이라고 어떻게 말할 수 있습니까? 우리는 코드를 사용하지 않습니다.

안타깝게도 구어체 사용에서이 단어 inheritance는 클래스가 인터페이스를 구현할 때 여전히 자주 사용되지만 interface implementationIMO라는 용어 inheritance는 구체적이거나 추상적 인 클래스의 상속과 함께 엄격하게 사용되어야합니다. C ++ 및 C #과 같은 언어에서는 클래스 상속과 인터페이스 구현 모두에 동일한 구문 (예 : Subclass : SuperclassClass : Interface)이 사용되며, 이는 inheritance인터페이스를 통한 단어 오용의 확산에 기여했을 수 있습니다 . Java는 인터페이스 extend를 사용 implement하는 것과는 반대로 클래스를 사용하기 위한 구문이 다릅니다 . 이는 좋은 것입니다.

Q2 인터페이스 구현이 상속이 아닌 경우 인터페이스를 사용하여 다중 상속을 달성하는 방법은 무엇입니까?

한 클래스에 여러 인터페이스를 구현 한 다음 클래스의 모든 인터페이스에 필요한 모든 메서드, 속성 및 이벤트에 대한 구현을 제공하여 구성을 통해 다중 상속의 '효과'를 얻을 수 있습니다. 구체적인 클래스로이를 수행하는 일반적인 기술 중 하나는 구현을 각 내부 클래스 구현에 '연결'하여 외부 인터페이스를 구현하는 클래스와 'has-a'(구성) 관계를 수행하는 것입니다. (C ++와 같은 언어는 다중 구체적인 상속을 직접 지원하지만 다이아몬드 문제와 같은 다른 잠재적 인 문제를 생성합니다.)

Q3 인터페이스를 사용하면 어떤 이점이 있습니까? 그들은 코드가 없습니다. 우리는 그것을 구현하는 모든 클래스에서 코드를 반복해서 작성해야합니다.

인터페이스를 사용하면 기존 클래스 (예 : 프레임 워크)가 알려진 인터페이스를 통해 통신 할 수 있기 때문에 이전에 '본 적이없는'새 클래스와 상호 작용할 수 있습니다. 인터페이스를 계약이라고 생각하십시오. 이 인터페이스를 클래스에 구현하면 계약 상 필요한 의무를 충족 할 수 있으며이 계약이 구현되면 클래스를 인터페이스를 사용하는 다른 코드와 상호 교환하여 사용할 수 있어야합니다.

실제 사례

'실제 세계'의 예는 특정 국가의 전기 콘센트를 둘러싼 법률 및 협약 (인터페이스)입니다. 소켓에 연결된 각 전기 제품은 당국이 소켓에 대해 정의한 사양 (계약)을 충족해야합니다 (예 : 라인의 위치, 중성선 및 접지선, 켜기 / 끄기 스위치의 위치 및 색상, 적합성) interface스위치를 켰을 때 공급되는 전압, 주파수 및 최대 전류 .

와이어를 납땜하는 것보다 인터페이스 (예 : 표준 벽면 소켓)를 분리 할 때의 이점은 팬, 주전자, 이중 어댑터 또는 내년에 발명 될 새 기기를 연결할 수 있다는 것입니다. , 인터페이스를 설계 할 때이 어플라이언스가 없었음에도 불구하고. 왜? 인터페이스의 요구 사항을 준수 하기 때문입니다 .

인터페이스를 사용하는 이유는 무엇입니까?

인터페이스는 클래스의 느슨한 결합에 적합하며 Bob 삼촌의 SOLID 패러다임, 특히 Dependency Inversion PrincipleInterface Segregation Principles.

간단히 말해, 클래스 간의 종속성이 다른 구체적인 클래스가 아닌 인터페이스 (추상화)에서만 결합되도록함으로써 종속성을 인터페이스의 요구 사항을 충족하는 다른 클래스 구현으로 대체 할 수 있습니다.

테스트에서 종속성의 스텁과 모의를 사용하여 각 클래스를 단위 테스트 할 수 있으며 클래스와 종속성과의 상호 작용을 '스파이'할 수 있습니다.


이것은 매우 오래된 질문이며 java-8 릴리스는 인터페이스에 더 많은 기능과 힘을 추가했습니다.

인터페이스 선언은 다음을 포함 할 수 있습니다.

  1. 메서드 서명
  2. 기본 방법
  3. 정적 메서드
  4. 상수 정의.

인터페이스에 구현이있는 유일한 메서드는 기본 메서드 정적 메서드입니다.

인터페이스 사용 :

  1. 계약 을 정의하려면
  2. 관련되지 않은 클래스를 연결하려면 기능이 있습니다 (예 : Serializable 인터페이스를 구현하는 클래스는 해당 인터페이스를 구현하는 것을 제외하고 그들 사이에 관계가있을 수도 있고 없을 수도 있습니다)
  3. 교환 가능한 구현 을 제공하려면Strategy_pattern
  4. 기본 메소드를 사용하면 라이브러리의 인터페이스에 새 기능을 추가하고 해당 인터페이스의 이전 버전 용으로 작성된 코드와 바이너리 호환성보장 할 수 있습니다.
  5. 정적 메서드를 사용하여 라이브러리에서 도우미 메서드를 구성 합니다 (별도의 클래스가 아닌 동일한 인터페이스에서 인터페이스에 특정한 정적 메서드를 유지할 수 있음).

개념을 더 잘 이해하려면 코드 예제에 대한이 관련 SE 질문을 살펴보십시오.

Interface와 Abstract 클래스의 차이점을 어떻게 설명해야합니까?

검색어로 돌아갑니다.

Q1. 인터페이스에는 추상 메서드 (코드 없음) 만 있기 때문에 인터페이스를 구현하는 경우 상속이라고 어떻게 말할 수 있습니까? 우리는 코드를 사용하지 않습니다.

Q2. 인터페이스 구현이 상속이 아닌 경우 다중 상속을 달성하기 위해 인터페이스를 어떻게 사용합니까?

인터페이스에는 정적기본 메서드에 대한 코드가 포함될 수 있습니다 . 이러한 기본 메서드는 이전 버전과의 호환성을 제공하고 정적 메서드는 도우미 / 유틸리티 기능을 제공 합니다.

당신은 자바에서 진정한 다중 상속을 가질 수 없으며 인터페이스는 그것을 얻는 방법이 아닙니다. 인터페이스는 상수 만 포함 할 수 있습니다. 따라서 상태를 상속 할 수 없지만 동작을 구현할 수 있습니다.

상속능력으로 바꿀 수 있습니다 . 인터페이스는 클래스 구현에 여러 기능을 제공합니다.

Q3. 어쨌든 인터페이스 사용의 이점은 무엇입니까? 그들은 코드가 없습니다. 우리는 그것을 구현하는 모든 클래스에서 코드를 반복해서 작성해야합니다.

내 대답의 " 인터페이스 사용 "섹션을 참조하십시오 .


상속은 한 클래스가 다른 클래스 (추상적 일 수 있음) 또는 인터페이스에서 파생되는 경우입니다. 객체 지향 (상속)의 가장 큰 장점은 코드 재사용 (여러 가지 방법이 있음)이 아니라 다형성입니다.

다형성은 인터페이스를 사용하는 코드가있는 경우이며, 인스턴스 객체는 해당 인터페이스에서 파생 된 모든 클래스가 될 수 있습니다. 예를 들어, public void Pet (IAnimal animal)과 같은 메소드를 가질 수 있으며이 메소드는 IAnimal에서 상속 된 Dog 또는 Cat의 인스턴스 인 객체를 가져옵니다. 또는 다음과 같은 코드를 가질 수 있습니다 : IAnimal animal 그런 다음이 인터페이스의 메서드를 호출 할 수 있습니다 : animal.Eat () Dog 또는 Cat이 다른 방식으로 구현할 수 있습니다.

인터페이스의 가장 큰 장점은 인터페이스 중 일부에서 상속 할 수 있다는 것입니다. 그러나 하나만 상속해야하는 경우 추상 클래스도 사용할 수 있습니다. 다음은 추상 클래스와 인터페이스의 차이점에 대해 자세히 설명하는 기사입니다. http://www.codeproject.com/KB/cs/abstractsvsinterfaces.aspx


오래된 질문. 누구도 표준 소스를 인용하지 않았다는 사실에 놀랐습니다. Java : an Overview by James Gosling, Design Patterns : Elements of Reusable Object-Oriented Software by the Gang of Four 또는 Effective Java by Joshua Bloch (다른 소스 중에서).

인용문으로 시작하겠습니다.

인터페이스는 단순히 객체가 응답하는 메소드 세트의 사양입니다. 인스턴스 변수 나 구현은 포함되지 않습니다. 인터페이스는 (클래스와 달리) 다중 상속 될 수 있으며 일반적인 엄격한 클래스 상속 구조보다 더 유연한 방식으로 사용될 수 있습니다. (고슬링, p. 8)

이제 가정과 질문을 하나씩 살펴 보겠습니다 (자바로 Java 8 기능은 무시하겠습니다).

가정

인터페이스는 오직 추상 메소드와 최종 필드의 모음입니다.

abstractJava 인터페이스 에서 키워드 보았습니까 ? 아니요. 그러면 인터페이스를 추상 메서드 모음으로 간주해서는 안됩니다. 순수한 가상 메서드 만있는 클래스 인 C ++ 소위 인터페이스에 오해를받을 수도 있습니다. C ++는 설계 상 여러 가지 상속이 있기 때문에 인터페이스가 없습니다 (필요하지도 않음).

Gosling이 설명했듯이 인터페이스를 "객체가 응답하는 일련의 메소드"로 간주해야합니다. 인터페이스 와 관련 문서 를 서비스 계약 으로보고 싶습니다 . 해당 인터페이스를 구현하는 객체에서 기대할 수있는 내용을 설명합니다. 문서는 사전 및 사후 조건 (예 : 매개 변수가 null이 아니어야하고 출력은 항상 양수, ...) 및 불변 (객체 내부 상태를 수정하지 않는 방법)을 지정해야합니다. 이 계약은 OOP의 핵심이라고 생각합니다.

Java에는 다중 상속이 없습니다.

과연.

JAVA는 우리 경험상 혜택보다 더 많은 슬픔을 가져다주는 C ++의 거의 사용되지 않고 잘 이해되지 않고 혼란스러운 기능을 많이 생략했습니다. 이것은 주로 연산자 오버로딩 (메서드 오버로딩이 있지만), 다중 상속 및 광범위한 자동 강제로 구성됩니다. (Gosling, 2 페이지)

추가 할 항목이 없습니다.

인터페이스를 사용하여 Java에서 다중 상속을 수행 할 수 있습니다.

아니요, Java에는 다중 상속이 없기 때문에 간단합니다. 위 참조.

상속의 강점 중 하나는 파생 클래스에서 기본 클래스의 코드를 다시 작성하지 않고도 사용할 수 있다는 것입니다. 이것이 상속에있어 가장 중요한 일이 될 수 있습니다.

이를 "구현 상속"이라고합니다. 작성한대로 코드를 재사용하는 편리한 방법입니다.

그러나 중요한 대응책이 있습니다.

부모 클래스는 종종 하위 클래스의 물리적 표현의 적어도 일부를 정의합니다. 상속은 부모의 구현에 대한 세부 사항에 하위 클래스를 노출하기 때문에 "상속은 캡슐화를 중단한다"[Sny86]라고 종종 말합니다. 하위 클래스의 구현은 상위 클래스의 구현과 너무 얽혀있어서 상위 구현의 변경으로 인해 하위 클래스가 변경됩니다. (GOF, 1.6)

(Bloch, 항목 16에 유사한 인용문이 있습니다.)

실제로 상속은 또 다른 목적으로 사용됩니다.

클래스 상속은 인터페이스 상속과 구현 상속을 결합합니다. 인터페이스 상속은 하나 이상의 기존 인터페이스 측면에서 새 인터페이스를 정의합니다. 구현 상속은 하나 이상의 기존 구현 측면에서 새로운 구현을 정의합니다. (GOF, 부록 A)

둘 다 extendsJava 에서 키워드 사용합니다 . 클래스 계층 구조와 인터페이스 계층 구조가있을 수 있습니다. 첫 번째는 구현을 공유하고 두 번째는 의무를 공유합니다.

질문

Q1. 인터페이스에는 추상 메서드 (코드 없음) 만 있기 때문에 인터페이스를 구현하는 경우 상속이라고 어떻게 말할 수 있습니까? 우리는 그 코드를 사용하지 않습니다. **

인터페이스 구현은 상속이 아닙니다. 구현입니다. 따라서 키워드 implements.

Q2. 인터페이스 구현이 상속이 아닌 경우 다중 상속을 달성하기 위해 인터페이스를 어떻게 사용합니까? **

Java에서는 다중 상속이 없습니다. 위 참조.

Q3. 어쨌든 인터페이스 사용의 이점은 무엇입니까? 그들은 코드가 없습니다. 구현하는 모든 클래스에서 코드를 반복해서 작성해야합니다 ./ 그런 다음 인터페이스를 만들어야하는 이유는 무엇입니까? / 인터페이스 사용의 정확한 이점은 무엇입니까? 인터페이스를 사용하여 달성 한 것이 실제로 다중 상속입니까?

가장 중요한 질문은 다음 과 같습니다. 다중 상속을 원하는 이유는 무엇입니까? 두 가지 대답을 생각할 수 있습니다. 1. 객체에 여러 유형을 부여합니다. 2. 코드를 재사용합니다.

개체에 여러 유형 제공

OOP에서 하나의 객체는 다른 유형을 가질 수 있습니다 . 자바 예를 들어,는 ArrayList<E>다음과 같은 유형이있다 : Serializable, Cloneable, Iterable<E>, Collection<E>, List<E>, RandomAccess, AbstractList<E>, AbstractCollection<E>그리고 Object(내가 사람을 잊지 않고 희망). 개체에 다른 유형이 있으면 다양한 소비자가 그 특이성을 알지 못해도 사용할 수 있습니다. 나는 필요 Iterable<E>하고 당신은 나에게 줘 ArrayList<E>? 괜찮아. 그러나 지금 a가 필요 List<E>하고 당신이 나에게을 주면 ArrayList<E>괜찮습니다. 기타.

OOP에서 개체를 어떻게 입력합니까? 당신은했다 Runnable예를 들어 인터페이스를,이 예는이 질문에 대한 답을 설명하기에 적합합니다. 공식 Java 문서를 인용합니다.

또한 Runnable은 Thread를 서브 클래 싱하지 않는 동안 클래스가 활성화되는 수단을 제공합니다.

요점은 다음과 같습니다. 상속은 개체 입력 하는 편리한 방법입니다 . 스레드를 만들고 싶습니까? 클래스를 서브 클래 싱합시다 Thread. 객체가 다른 유형을 갖기를 원하면 다중 상속을 사용합시다. 아아. Java에는 존재하지 않습니다. (C ++에서 객체가 다른 유형을 갖기를 원한다면 다중 상속이가는 길입니다.)

객체에 여러 유형을 부여하는 방법은 무엇입니까? Java에서는 객체를 직접 입력 할 수 있습니다 . 그것이 당신의 클래스 implementsRunnable인터페이스 일 때 하는 일 입니다. Runnable상속의 팬이라면 왜 사용 합니까? 클래스가 이미 다른 클래스의 하위 클래스이기 때문일 수 있습니다 A. 이제 클래스에는 ARunnable.

여러 인터페이스를 사용하면 개체에 여러 유형을 제공 할 수 있습니다. implements다중 인터페이스 클래스를 생성하기 만하면 됩니다. 계약을 준수하는 한 괜찮습니다.

코드 재사용

이것은 어려운 주제입니다. 캡슐화를 깨는 것에 대해 이미 GOF를 인용했습니다. 다른 답변은 다이아몬드 문제를 언급했습니다. 단일 책임 원칙을 생각할 수도 있습니다.

클래스는 변경해야하는 이유가 하나만 있어야합니다. (Robert C. Martin, 애자일 소프트웨어 개발, 원칙, 패턴 및 관행)

부모 클래스가 있으면 클래스 자체의 책임 외에도 변경해야 할 이유가있을 수 있습니다.

슈퍼 클래스의 구현은 릴리스마다 변경 될 수 있으며, 변경되면 해당 코드가 건드리지 않은 경우에도 하위 클래스가 중단 될 수 있습니다. 결과적으로 하위 클래스는 수퍼 클래스와 함께 진화해야합니다 (Bloch, 항목 16).

좀 더 평범한 문제를 추가하겠습니다. 클래스에서 메서드의 소스 코드를 찾으려고 할 때 항상 이상한 느낌이 들지만 찾을 수 없습니다. 그런 다음 기억합니다. 부모 클래스의 어딘가에 정의되어야합니다. 또는 조부모 수업에서. 아니면 더 높을 수도 있습니다. 좋은 IDE는이 경우 귀중한 자산이지만 내 마음 속에는 마법 같은 것이 남아 있습니다. 인터페이스 계층 구조와 비슷한 것은 없습니다. javadoc 만 필요하기 때문입니다. IDE에서 하나의 키보드 단축키를 사용하면 얻을 수 있습니다.

상속 하우 워에는 다음과 같은 장점이 있습니다.

하위 클래스 및 수퍼 클래스 구현이 동일한 프로그래머의 제어를받는 패키지 내에서 상속을 사용하는 것이 안전합니다. 또한 확장을 위해 특별히 디자인되고 문서화 된 클래스를 확장 할 때 상속을 사용하는 것이 안전합니다 (항목 17 : 상속을위한 디자인 및 문서화 또는 금지). (Bloch, 항목 16)

Java에서 "확장을 위해 특별히 설계되고 문서화 된"클래스의 예는 AbstractList.

그러나 Bloch와 GOF는 "상속보다 구성을 선호하십시오"라고 주장합니다.

위임은 상속처럼 재사용을 위해 구성을 강력하게 만드는 방법입니다 [Lie86, JZ91]. 위임에서는 두 개의 개체가 요청 처리에 관여합니다. 수신 개체는 작업을 대리인에게 위임합니다. 이것은 부모 클래스에 대한 요청을 지연시키는 서브 클래스와 유사합니다. (GOF 32 페이지)

컴포지션을 사용하면 동일한 코드를 반복해서 작성할 필요가 없습니다. 중복을 처리하는 클래스를 만들고이 클래스의 인스턴스를 인터페이스를 구현하는 클래스에 전달하기 만하면됩니다. 코드를 재사용하는 매우 간단한 방법입니다. 그리고 이는 단일 책임 원칙을 따르고 코드를보다 테스트 가능하게 만드는 데 도움이됩니다. Rust와 Go에는 상속이 없지만 (클래스도 없음) 다른 OOP 언어보다 코드가 더 중복되지 않는다고 생각합니다.

또한 컴포지션을 사용하면 자연스럽게 인터페이스를 사용하여 코드에 필요한 구조와 유연성을 제공 할 수 있습니다 (인터페이스 사용 사례에 대한 다른 답변 참조).

참고 : Java 8 인터페이스와 코드를 공유 할 수 있습니다.

마지막으로 마지막 인용문 :

기억에 남는 Q & A 세션에서 누군가가 [James Gosling]에게 "Java를 다시 할 수 있다면 무엇을 바꾸고 싶습니까?"라고 물었습니다. "수업을 그만두 겠어요"(인터넷 어디에서나 이것이 사실인지 모르겠다)


두 방법 모두 작동합니다 (인터페이스 및 다중 상속).

빠르고 실용적인 짧은 답변

인터페이스는 메서드 정의 만 있고 코드가 전혀없는 슈퍼 클래스가있는 다중 상속을 사용하여 수년 간의 경험이있을 때 더 좋습니다.

보완적인 질문은 "추상 클래스에서 인터페이스로 코드를 마이그레이션하는 방법과 이유"일 수 있습니다.

애플리케이션에서 추상 클래스를 많이 사용하지 않거나 경험이 많지 않은 경우 인터페이스를 건너 뛰는 것이 좋습니다.

인터페이스를 서두르지 마십시오.

긴 지루한 답변

인터페이스는 추상 클래스와 매우 유사하거나 동일합니다.

코드에 추상 클래스가 많으면 인터페이스 측면에서 생각하기 시작할 때입니다.

추상 클래스가있는 다음 코드 :


MyStreamsClasses.java

/* File name : MyStreamsClasses.java */
import java.lang.*;
// Any number of import statements

public abstract class InputStream {
  public void ReadObject(Object MyObject);
}

public abstract class OutputStream {
  public void WriteObject(Object MyObject);
}

public abstract class InputOutputStream 
    imnplements InputStream, OutputStream {
  public void DoSomethingElse();
}

다음으로 대체 가능 :


MyStreamsInterfaces.java

/* File name : MyStreamsInterfaces.java */
import java.lang.*;
// Any number of import statements

public interface InputStream {
  public void ReadObject(Object MyObject);
}

public interface OutputStream {
  public void WriteObject(Object MyObject);
}

public interface InputOutputStream 
    extends InputStream, OutputStream {
  public void DoSomethingElse();
}

건배.


Q1. 인터페이스에는 추상 메서드 (코드 없음) 만 있으므로 인터페이스를 구현하면 상속이라고 어떻게 말할 수 있습니까? 우리는 코드를 사용하지 않습니다.

동등한 상속이 아닙니다. 그것은 단지 유사합니다. 설명하겠습니다.

VolvoV3 extends VolvoV2, and VolvoV2 extends    Volvo (Class)
VolvoV3 extends VolvoV2, and VolvoV2 implements Volvo (Interface)

line1: Volvo v = new VolvoV2(); 
line2: Volvo v = new VolvoV3(); 

line1과 line2 만 표시되는 경우 VolvoV2와 VolvoV3의 유형이 동일하다고 추론 할 수 있습니다. Volvo가 슈퍼 클래스인지 아니면 Volvo가 인터페이스인지 추론 할 수 없습니다.

Q2. 인터페이스 구현이 상속이 아닌 경우 여러 상속을 달성하기 위해 인터페이스를 어떻게 사용합니까?

이제 인터페이스 사용 :

VolvoXC90 implements XCModel and Volvo (Interface)
VolvoXC95 implements XCModel and Volvo (Interface)

line1: Volvo   a = new VolvoXC90();
line2: Volvo   a = new VolvoXC95();
line3: XCModel a = new VolvoXC95();

line1과 line2 만 표시되면 VolvoXC90과 VolvoXC95가 동일한 유형 (Volvo)을 가지고 있다고 추론 할 수 있습니다. Volvo가 슈퍼 클래스이거나 Volvo가 인터페이스라고 추론 할 수 없습니다.

line2와 line3 만 보이면 Volvo95가 XCModel과 Volvo라는 두 가지 유형을 구현하고 있음을 추론 할 수 있습니다. Java에서 적어도 하나는 인터페이스 여야한다는 것을 알고 있습니다. 예를 들어이 코드가 C ++로 작성된 경우 두 클래스 모두가 될 수 있습니다. 따라서 다중 상속.

Q3. 어쨌든 인터페이스 사용의 이점은 무엇입니까? 그들은 코드가 없습니다. 우리는 그것을 구현하는 모든 클래스에서 코드를 반복해서 작성해야합니다.

200 개의 다른 클래스에서 VolvoXC90 클래스를 사용하는 시스템을 상상해보십시오.

VolvoXC90 v = new VolvoXC90();

VolvoXC95를 시작하기 위해 시스템을 발전시켜야하는 경우 200 개의 다른 클래스를 변경해야합니다.

이제 10,000,000 개의 클래스에서 Volvo 인터페이스를 사용하는 시스템을 상상해보십시오.

// Create VolvoXC90 but now we need to create VolvoXC95
Volvo v = new VolvoFactory().newCurrentVolvoModel(); 

이제 VolvoXC95 모델을 생성하기 위해 시스템을 발전시켜야하는 경우 하나의 클래스 인 Factory 만 변경하면됩니다.

상식적인 질문입니다. 시스템이 소수의 클래스로만 구성되고 업데이트가 거의없는 경우 모든 곳에서 인터페이스를 사용하면 비생산적입니다. 대형 시스템의 경우 많은 고통을 줄이고 인터페이스를 채택하는 위험을 피할 수 있습니다.

SOLID 원칙에 대해 자세히 읽어보고 Effective Java 책을 읽어 보는 것이 좋습니다. 경험 많은 소프트웨어 엔지니어로부터 좋은 교훈을 얻었습니다.


인터페이스는 클래스가 인터페이스 내에서 기능을 구현하고 해당 인터페이스에 따라 동작하도록 만들어집니다.


그래서. 여기에 인터페이스가 무엇인지 자세히 설명하는 훌륭한 답변이 많이 있습니다. 그러나 이것은 나의 최고의 동료 중 한 명이 지난 몇 년 동안 대학에서 배운 것을 혼합하여 몇 년 전에 나에게 설명했던 방식으로 그 사용의 예입니다.

인터페이스는 일종의 '계약'입니다. 사용 가능한 일부 메서드, 필드 등을 노출합니다. 구현 세부 정보는 표시하지 않고 반환하는 내용과 사용하는 매개 변수 만 표시합니다. 그리고 여기에 3 번 질문에 대한 답이 있습니다. 제가 느끼는 것은 현대 OOP의 가장 큰 강점 중 하나입니다.

"수정이 아닌 추가에 의한 코드" -Magnus Madsen, AAU

그게 그가 적어도 이름을 불렀고 다른 곳에서 가져 왔을 수도 있습니다. 아래 샘플 코드는 C #으로 작성되었지만 표시된 모든 것은 Java에서도 거의 동일한 방식으로 수행 될 수 있습니다.

우리가 보는 것은 IOContext라는 단일 필드가있는 SampleApp이라는 클래스입니다. IOContext는 인터페이스입니다. SampleApp은 "doSomething ()"메서드에서 데이터를 저장하는 방법에 대해 한 가지 재치를 신경 쓰지 않습니다.

개발 프로세스 초기에 데이터를 저장하는 것이 저장 방법보다 중요했을 수 있으므로 개발자는 단순히 FileContext 클래스를 작성하기로 선택했습니다. 그러나 나중에 그는 어떤 이유로 든 JSON을 지원해야했습니다. 그래서 그는 FileContext를 상속하는 JSONFileContext 클래스를 작성했습니다. 이것은 사실상 FileContext의 기능을 가진 IOContext이고, FileContexts SaveData 및 LoadData의 대체를 저장하고, 여전히 '쓰기 / 읽기'메소드를 사용함을 의미합니다.

JSON 클래스를 구현하는 것은 클래스를 작성하고 IOContext를 상속받는 것과 비교하여 약간의 작업이었습니다.

SampleApp의 필드는 'FileContext'유형일 수 있지만 그렇게하면 해당 클래스의 하위 항목 만 사용하도록 제한되었을 것입니다. 인터페이스를 만들면 SQLiteContext 구현도 할 수 있고 데이터베이스에 쓸 수도 있습니다. SampleApp은 절대 알거나 신경 쓰지 않습니다. SQL lite 클래스를 작성했을 때 코드를 한 번만 변경하면 new JSONFileContext();됩니다.new SQLiteContext();

우리는 여전히 오래된 구현을 가지고 있으며 필요한 경우 다시 구현할 수 있습니다. 우리는 아무것도 깨뜨리지 않았고 우리 코드의 모든 변경 사항은 반 줄이며 눈 깜짝 할 사이에 다시 변경할 수 있습니다.

그래서 : 수정이 아닌 추가에 의한 코드.

namespace Sample
{
    class SampleApp
    {
        private IOContext context;

        public SampleApp()
        {
            this.context = new JSONFileContext(); //or any of the other implementations
        }

        public void doSomething()
        {
            //This app can now use the context, completely agnostic of the actual implementation details.
            object data = context.LoadData();
            //manipulate data
            context.SaveData(data);
        }
    }

    interface IOContext
    {
        void SaveData(object data);
        object LoadData();
    }

    class FileContext : IOContext
    {
        public object LoadData()
        {

            object data = null;
            var fileContents = loadFileContents();
            //Logic to turn fileContents into a data object
            return data;
        }

        public void SaveData(object data)
        {
            //logic to create filecontents from 'data'
            writeFileContents(string.Empty);
        }

        protected void writeFileContents(string fileContents)
        {
            //writes the fileContents to disk
        }

        protected string loadFileContents()
        {
            string fileContents = string.Empty;
            //loads the fileContents and returns it as a string
            return fileContents;
        }
    }

    class JSONFileContext : FileContext
    {
        public new void SaveData(object data)
        {
            //logic to create filecontents from 'data'
            base.writeFileContents(string.Empty);
        }

        public new object LoadData()
        {
            object data = null;
            var fileContents = loadFileContents();
            //Logic to turn fileContents into a data object
            return data;
        }
    }

    class SQLiteContext : IOContext
    {
        public object LoadData()
        {
            object data = null;
            //logic to read data into the data object
            return data;
        }

        public void SaveData(object data)
        {
            //logic to save the data object in the database
        }
    }
}

인터페이스

An interface is a contract defining how to interact with an object. They are useful to express how your internals intend to interact with an object. Following Dependency Inversion your public API would have all parameters expressed with interfaces. You don't care how it does what you need it to do, just that it does exactly what you need it to do.

Example: You may simply need a Vehicle to transport goods, you don't care about the particular mode of transport.

Inheritance

Inheritance is an extension of a particular implementation. That implementation may or may not satisfy a particular interface. You should expect an ancestor of a particular implementation only when you care about the how.

Example: You may need a Plane implementation of a vehicle for fast transport.

Composition

Composition can be used as an alternative to inheritance. Instead of your class extending a base class, it is created with objects that implement smaller portions of the main class's responsibility. Composition is used in the facade pattern and decorator pattern.

Example: You may create a DuckBoat (DUKW) class that implements LandVehicle and WaterVehicle which both implement Vehicle composed of Truck and Boat implementations.

Answers

Q1. As interfaces are having only abstract methods (no code) so how can we say that if we are implementing any interface then it is inheritance ? We are not using its code.

Interfaces are not inheritance. Implementing an interface expresses that you intend for your class to operate in the way that is defined by the interface. Inheritance is when you have a common ancestor, and you receive the same behavior (inherit) as the ancestor so you do not need to define it.

Q2. If implementing an interface is not inheritance then How interfaces are used to achieve multiple inheritance ?

Interfaces do not achieve multiple inheritance. They express that a class may be suitable for multiple roles.

Q3. Anyhow what is the benefit of using Interfaces ? They are not having any code. We need to write code again and again in all classes we implement it.

One of the major benefits of interfaces is to provide separation of concerns:

  • You can write a class that does something with another class without caring how that class is implemented.
  • Any future development can be compatible with your implementation without needing to extend a particular base class.

In the spirit of DRY you can write an implementation that satisfies an interface and change it while still respecting the open/closed principal if you leverage composition.

참고URL : https://stackoverflow.com/questions/8531292/why-to-use-interfaces-multiple-inheritance-vs-interfaces-benefits-of-interface

반응형