용어 : 언어 구조 interface
를 interface로 , 유형 또는 객체의 인터페이스를 표면으로 표현합니다 (더 나은 용어가없는 경우).
구체적인 유형 대신 추상화에 의존하는 객체를 가짐으로써 느슨한 결합을 달성 할 수 있습니다.
옳은.
이를 통해 두 가지 주요 이유로 느슨한 커플 링이 가능합니다. 1- 추상화가 콘크리트 유형보다 변경 될 가능성이 낮아서 종속 코드가 중단 될 가능성이 적습니다. 2- 다른 콘크리트 유형은 모두 추상화에 맞기 때문에 런타임에 사용할 수 있습니다. 기존의 종속 코드를 변경할 필요없이 새로운 콘크리트 유형을 나중에 추가 할 수도 있습니다.
정확하지 않습니다. 현재 언어는 일반적으로 추상화가 변경 될 것으로 예상하지는 않습니다 (그러나이를 처리 할 디자인 패턴이 있지만). 일반 사항과 세부 사항을 분리하는 것은 추상화입니다. 이것은 보통 추상 계층에 의해 수행됩니다 . 이 계층은이 추상화에 기반한 코드를 손상시키지 않고 다른 특정 사항으로 변경할 수 있습니다. 느슨한 결합이 이루어집니다. 비 OOP 예 : sort
루틴이 버전 1의 Quicksort에서 버전 2의 Tim Sort로 변경 될 수 있습니다 . 따라서 정렬중인 결과에만 의존하는 코드 (즉, sort
추상화에 기반한 코드 )는 실제 정렬 구현에서 분리됩니다.
위에서 표면 이라고 부르는 것은 추상화 의 일반적인 부분 입니다. OOP에서 하나의 객체가 때때로 여러 추상화를 지원해야합니다. A-확실히하지 최적의 예 : 자바의 java.util.LinkedList
모두 지원 List
은 "주문, 색인 모음"추상화에 대해, 그리고 지원 인터페이스 Queue
(거친 용어)은 "FIFO"추상화에 관한 인터페이스를.
객체가 여러 추상화를 어떻게 지원할 수 있습니까?
C ++에는 인터페이스가 없지만 다중 상속, 가상 메소드 및 추상 클래스가 있습니다. 그런 다음 추상화는 가상 메소드를 선언하지만 정의하지 않는 추상 클래스 (즉, 즉시 인스턴스화 할 수없는 클래스)로 정의 할 수 있습니다. 그런 다음 추상화의 세부 사항을 구현하는 클래스는 해당 추상 클래스에서 상속하고 필요한 가상 메서드를 구현할 수 있습니다.
여기에서 문제는 다중 상속으로 인해 다이아몬드 문제가 발생할 수 있으며 , 클래스에서 메소드 구현을 검색하는 순서 (MRO : 메소드 해결 순서)가 "모순"을 초래할 수 있습니다. 이에 대한 두 가지 응답이 있습니다.
정상적인 순서를 정의하고 현명하게 선형화 할 수없는 순서를 거부하십시오. C3 MRO는 매우 합리적이고 잘 작동합니다. 1996 년에 출판되었다.
쉬운 경로를 통해 여러 상속을 거부하십시오.
Java는 후자의 옵션을 취하여 단일 행동 상속을 선택했습니다. 그러나 여전히 다중 추상화를 지원하는 객체의 기능이 필요합니다. 따라서 메소드 정의를 지원하지 않고 선언 만 지원하는 인터페이스를 사용해야합니다.
결과적으로 MRO는 명확하고 (각 수퍼 클래스를 순서대로 살펴보십시오), 객체는 여러 추상화에 대해 여러 표면을 가질 수 있습니다.
이것은 종종 약간의 행동이 표면의 일부이기 때문에 다소 불만족스러운 것으로 판명되었습니다. Comparable
인터페이스를 고려하십시오 .
interface Comparable<T> {
public int cmp(T that);
public boolean lt(T that); // less than
public boolean le(T that); // less than or equal
public boolean eq(T that); // equal
public boolean ne(T that); // not equal
public boolean ge(T that); // greater than or equal
public boolean gt(T that); // greater than
}
이것은 매우 사용자 친화적이지만 (편리한 방법이 많은 멋진 API) 구현하기가 지루합니다. 우리는 인터페이스가 오직 cmp
하나의 필수 메소드 측면에서 자동으로 다른 메소드를 포함 하고 구현 하기를 원합니다 . 믹스 인 , 그러나 더 중요한 것은 특성 [ 1 ], [ 2 ]가 다중 상속의 함정에 빠지지 않고이 문제를 해결합니다.
이는 특성이 MRO에 실제로 참여하지 않도록 특성 구성을 정의하여 수행됩니다. 대신 정의 된 메소드가 구현 클래스로 구성됩니다.
Comparable
인터페이스는 스칼라로서 표현 될 수있다
trait Comparable[T] {
def cmp(that: T): Int
def lt(that: T): Boolean = this.cmp(that) < 0
def le(that: T): Boolean = this.cmp(that) <= 0
...
}
클래스가 해당 특성을 사용하면 다른 메소드가 클래스 정의에 추가됩니다.
// "extends" isn't different from Java's "implements" in this case
case class Inty(val x: Int) extends Comparable[Inty] {
override def cmp(that: Inty) = this.x - that.x
// lt etc. get added automatically
}
그래서 Inty(4) cmp Inty(6)
것 -2
및 Inty(4) lt Inty(6)
것 true
.
많은 언어가 특성을 일부 지원하며 "MOP (Metaobject Protocol)"가있는 언어는 특성을 추가 할 수 있습니다. 최근 Java 8 업데이트에는 특성과 유사한 기본 메소드가 추가되었습니다 (인터페이스의 메소드는 대체 구현을 가질 수 있으므로 클래스를 구현하여 이러한 메소드를 구현하는 것이 선택 사항 임).
불행하게도, 특성은 상당히 최근의 발명 (2002)이므로 더 큰 주류 언어에서는 드물다.