추상 데이터 형식과 개체의 차이점은 무엇입니까?


11

Programmers.SE에 대한 답변은 Cook이 쓴 에세이 ( 객체는 ADT가 아님 )를 말합니다.

  • 객체는 대수식이 아닌 유형 값에 대한 특성 함수처럼 작동합니다. 객체는 유형 추상화가 아닌 절차 적 추상화를 사용합니다.

  • ADT는 일반적으로 프로그램에서 고유 한 구현을 갖습니다. 언어에 모듈이 있으면 ADT를 여러 번 구현할 수 있지만 일반적으로 상호 운용 할 수는 없습니다.

Cook의 논문에서 Cook의 논문에 사용 된 세트의 특정 예에서 객체를 특징적인 기능 으로 볼 수있는 경우가 있습니다 . 나는 객체, 일반적으로 특징적인 기능으로 볼 수 있다고 생각하지 않습니다.

또한, Aldritch의 논문 상호 운용성의 힘 : 객체가 불가피한 이유 ¹

Cook의 정의는 본질적으로 동적 디스패치를 ​​객체의 가장 중요한 특성으로 식별합니다.

그가 말했을 때 이것 과 Alan Kay에 동의

나에게 OOP는 메시징, 로컬 보존 및 상태 프로세스 숨기기 및 모든 것의 극단적 인 바인딩을 의미합니다.

그러나 Aldritch의 논문에 대한이 강의 슬라이드 는 Java 클래스 는 ADT이고 Java 인터페이스는 객체이며 실제로는 "객체"인터페이스를 사용하여 상호 운용 할 수 있음을 제안 합니다 (위의 글 머리 기호 중 하나에서 제공 한 OOP의 주요 기능 중 하나). ).

내 질문은

  1. 특징적인 기능이 물체의 주요 특징이 아니며 Frank Shearar가 잘못되었다고 말하는 것이 맞습니까?

  2. 동적 디스패치를 ​​사용하지 않더라도 Java 인터페이스를 통해 서로 통신하는 데이터가 객체의 예입니까? 왜? (내 이해는 동적 디스패치가 더 유연하고 인터페이스는 objective-C / smalltalk / erlang 스타일 메시징을 향한 발걸음이라는 것입니다.)

  3. 의존성 역전 원리의 개념은 ADT와 객체의 구별과 관련이 있습니까? ( Wikipedia 페이지 또는 Talking Objects : Message-Oriented Programming에 관한 이야기 참조 )이 개념을 처음 했지만 프로그램의 "계층"사이에 인터페이스를 추가한다는 것을 이해합니다 (wikipedia 페이지 다이어그램 참조).

  4. 원하는 경우 개체와 ADT의 차이점에 대한 다른 예 / 설명을 제공하십시오.

¹ 이 백서 (2013 년에 출판)는 읽기 쉬우 며 Cook의 2009 년 논문을 Java로 예제와 함께 요약합니다. 나는이 질문에 대답하지 말고 좋은 종이이기 때문에 적어도 그것을 감추는 것이 좋습니다.


5
흥미롭지 만 게시물 당 하나의 질문으로 제한하십시오.
Raphael

다소 미묘한 학문적 구별 / 토론 인 것 같습니다. ADT는 Java 및 기타 현대 OOP 언어와 같이 거의 객체입니다. 많은 OOP 언어에서 추상화는 객체가 (제한적 / 집중적 인 방식으로) 현실 세계를 모델링하는 방식으로 간주됩니다. 또한 참조 OOP에서 "추상"의 정의에 대한 혼동 , 소프트웨어 공학
vzn

답변:


8

구글은 유사한 양육 질문을대답 내가 아주 좋은 생각. 아래에 인용했습니다.

여기에 숨겨져있는 쿡 에세이에 설명되어있는 또 다른 차이점이 있습니다.

객체가 추상화를 구현하는 유일한 방법은 아닙니다. 모든 것이 대상이 아닙니다. 객체는 일부 사람들이 절차 적 데이터 추상화라고하는 것을 구현합니다. 추상 데이터 형식은 다른 형태의 추상화를 구현합니다.

이진 방법 / 함수를 고려할 때 중요한 차이점이 나타납니다. 절차 적 데이터 추상화 (객체)를 사용하면 Int 세트 인터페이스에 다음과 같이 작성할 수 있습니다.

interface IntSet {
  void unionWith(IntSet s);
  ...
}

이제 IntSet의 두 가지 구현을 고려하십시오. 하나는 목록으로 지원되고 다른 하나는보다 효율적인 이진 트리 구조로 지원됩니다.

class ListIntSet implements IntSet {
  void unionWith(IntSet s){ ... }
} 
class BSTIntSet implements IntSet {
  void unionWith(IntSet s){ ... }
}

unionWith는 IntSet 인수를 가져야합니다. ListIntSet 또는 BSTIntSet과 같은 더 구체적인 유형은 아닙니다. 이것은 BSTIntSet 구현이 입력이 BSTIntSet이라고 가정 할 수 없으며 그 사실을 사용하여 효율적인 구현을 제공한다는 것을 의미합니다. (일부 런타임 유형 정보를 사용하여이를 확인하고 더 효율적인 알고리즘을 사용할 수는 있지만 여전히 ListIntSet에 전달 될 수 있으며 덜 효율적인 알고리즘으로 대체되어야합니다).

이것을 서명 또는 헤더 파일에 다음과 같은 것을 작성할 수있는 ADT와 비교하십시오.

typedef struct IntSetStruct *IntSetType;
void union(IntSetType s1, IntSetType s2);

이 인터페이스에 대해 프로그래밍합니다. 특히, 유형은 추상적입니다. 당신은 그것이 무엇인지 알지 못합니다. 그런 다음 BST 구현을 통해 구체적인 유형과 작업을 제공합니다.

struct IntSetStruct {
 int value;
 struct IntSetStruct* left;
 struct IntSetStruct* right;
}

void union(IntSetType s1, IntSetType s2){ ... }

이제 Union은 실제로 s1과 s2의 구체적인 표현을 알고 있으므로 효율적인 구현을 위해이를 활용할 수 있습니다. 또한 목록 지원 구현을 작성하고 그 대신 연결하도록 선택할 수도 있습니다.

C (ish) 구문을 작성했지만 추상 데이터 형식 (예 : BSTImpl)을 정규화하여 대략 같은 프로그램에서 ADT의 구현을 두 개 이상 사용할 수있는 표준 ML을 참조해야합니다. IntSetStruct 및 ListImpl.IntSetStruct)

반대로 절차 데이터 추상화 (오브젝트)를 사용하면 이전 구현에서 작동하는 새로운 구현을 쉽게 도입 할 수 있습니다. 예를 들어, 사용자 정의 LoggingIntSet 구현을 작성하고이를 BSTIntSet과 통합 할 수 있습니다. 그러나 이것은 트레이드 오프입니다. 바이너리 방법에 대한 정보 유형을 잃어 버립니다! 종종 ADT 구현보다 더 많은 기능 및 구현 세부 사항을 인터페이스에 노출해야합니다. 이제 저는 쿡 에세이를 다시 입력하는 것처럼 느껴지므로 실제로 읽으십시오!

이에 대한 예를 추가하고 싶습니다.

Cook은 추상 데이터 형식의 예는 C의 모듈이라고 제안합니다. 실제로 C의 모듈에는 헤더 파일을 통해 내보내는 공용 함수와 그렇지 않은 정적 (비공개) 함수가 있기 때문에 정보 숨기기가 필요합니다. 또한 생성자 (예 : list_new ())와 관찰자 (예 : list_getListHead ())가 있습니다.

예를 들어 LIST_MODULE_SINGLY_LINKED라는 목록 모듈을 ADT로 만드는 핵심 요소는 모듈의 기능 (예 : list_getListHead ())이 "동일한 항목과 달리 LIST_MODULE_SINGLY_LINKED의 생성자에 의해 입력되는 데이터가 생성되었다고 가정한다는 것입니다 "목록 구현 (예 : LIST_MODULE_DYNAMIC_ARRAY). 이는 LIST_MODULE_SINGLY_LINKED의 기능이 구현시 특정 표현 (예 : 단일 링크 목록)을 가정 할 수 있음을 의미합니다.

LIST_MODULE_SINGLY_LINKED는 LIST_MODULE_DYNAMIC_ARRAY 생성자와 같이 생성 된 데이터를 피드 할 수 없기 때문에 LIST_MODULE_DYNAMIC_ARRAY와 상호 운용 할 수 없습니다.

이것은 추상 대수학에서 서로 다른 두 그룹이 상호 운용 할 수없는 방식과 유사합니다 (즉, 한 그룹의 요소를 다른 그룹의 요소와 곱할 수 없음). 이는 그룹이 그룹의 폐쇄 속성을 가정하기 때문입니다 (그룹의 요소 곱은 그룹에 있어야 함). 그러나 두 개의 다른 그룹이 실제로 다른 그룹 G의 하위 그룹임을 증명할 수있는 경우 G의 곱을 사용하여 두 그룹 각각에서 하나씩 두 개의 요소를 추가 할 수 있습니다.

ADT와 객체 비교

  • Cook은 ADT와 객체의 차이를 부분적으로 표현 문제에 연결합니다.. 대략 ADT는 함수형 프로그래밍 언어로 구현되는 일반 기능과 연결되는 반면 객체는 인터페이스를 통해 액세스하는 Java "객체"와 연결됩니다. 이 텍스트의 목적 상, 일반 함수는 ARGS와 TYPE 유형 (사전 조건)을 일부 인수로받는 함수입니다. TYPE에 따라 적절한 기능을 선택하고 ARGS (사후 조건)로 평가합니다. 일반 함수와 객체는 다형성을 구현하지만 일반 함수를 사용하면 일반 함수의 코드를 보지 않고 일반 함수에 의해 함수가 실행되는 프로그래머 KNOWS가 있습니다. 반면에 객체를 사용하면 프로그래머가 객체의 코드를 보지 않는 한 객체가 인수를 처리하는 방법을 프로그래머가 알지 못합니다.

  • 일반적으로 표현 문제는 "많은 표현이 있습니까?"의 관점에서 생각됩니다. vs. "표현이 거의없는 많은 기능이 있습니까?" 첫 번째 경우, 가장 일반적으로, 특히 Java에서와 같이 표현별로 코드를 구성해야합니다. 두 번째 경우에는 함수별로 코드를 구성해야합니다 (즉, 단일 일반 함수가 여러 표현을 처리 함).

  • 코드를 표현별로 구성한 경우 추가 기능 을 추가하려면 객체의 모든 표현에 기능을 추가 해야 합니다. 이런 의미에서 기능 추가는 "첨가"가 아닙니다. 기능별로 코드를 구성하는 경우 추가 표현을 추가하려는 경우 모든 객체에 표현을 추가 해야 합니다. 이런 의미에서 "첨가"가 아닌 표현을 추가합니다.

개체에 비해 ADT의 장점

  • 기능 추가는 부가 적

  • 성능을 위해 ADT 표현에 대한 지식을 활용하거나, ADT가 사전 조건이 주어진 후의 사후 조건을 보장 함을 증명할 수 있습니다. 이는 ADT를 사용한 프로그래밍이 올바른 순서대로 올바른 작업을 수행하는 것을 의미합니다 (사전 조건과 사후 조건을 "목표"사후 조건으로 연결).

ADT에 비해 개체의 장점

  • 덧셈에 표현 추가

  • 상호 운용 가능한 개체

  • 개체의 사전 / 사후 조건을 지정하고 ADT의 경우와 같이 이들을 함께 연결할 수 있습니다. 이 경우 객체의 장점은 (1) 인터페이스를 변경하지 않고 표현을 쉽게 변경하고 (2) 객체를 상호 운용 할 수 있다는 것입니다. 그러나 이것은 smalltalk의 의미에서 OOP의 목적을 무효화합니다. ( "Alan Kay의 OOP 버전"섹션 참조)

동적 디스패치는 OOP의 핵심

동적 디스패치 (즉, 후기 바인딩)는 객체 지향 프로그래밍에 필수적이라는 것이 명백 해졌다. 이것은 특정 표현을 가정하지 않는 일반적인 방법으로 프로 시저를 정의 할 수 있도록하기위한 것입니다. 구체적인 객체 지향 프로그래밍은 파이썬에서 쉽습니다. 특정 표현을 가정하지 않는 방식으로 객체의 메소드를 프로그래밍 할 수 있기 때문입니다. 그렇기 때문에 파이썬에는 Java와 같은 인터페이스가 필요하지 않습니다.

Java에서 클래스는 ADT입니다. 그러나 구현하는 인터페이스를 통해 액세스되는 클래스는 객체입니다.

부록 : Alan Kay의 OOP 버전

Alan Kay는 개체를 대수의 가족이라고 명시 적으로 언급했으며 Cook은 ADT가 대수라고 제안합니다. 따라서 Kay는 개체가 ADT의 패밀리라는 것을 의미했을 것입니다. 즉, 객체는 Java 인터페이스를 만족시키는 모든 클래스의 모음입니다.

그러나 Cook이 그린 물체 그림은 Alan Kay의 비전보다 훨씬 제한적입니다. 그는 객체가 네트워크의 컴퓨터 또는 생물학적 세포처럼 행동하기를 원했습니다. 아이디어는 프로그래밍에 대한 최소한의 노력의 원칙을 적용하여 상위 계층을 사용하여 ADT의 하위 계층을 쉽게 변경하도록하는 것이 었습니다. 이 그림을 염두에두고, Java 인터페이스는 객체가 메시지의 의미를 해석 하거나 완전히 무시할 없기 때문에 너무 제한적 입니다.

요약하자면, Kay의 객체의 핵심 아이디어는 객체 가 대수 군이라는 것이 아닙니다 (쿡이 강조한 것처럼). Kay의 핵심 아이디어는 대형 (네트워크의 컴퓨터)에서 작동하는 모델을 소형 (프로그램의 객체)에 적용하는 것이 었습니다.

편집 : Kay의 OOP 버전에 대한 또 다른 설명 : 객체의 목적은 선언적 이상에 더 가깝게 이동하는 것입니다. 절차 적 프로그래밍과 ADT의 관습과 같이 마이크로 매니지먼트가 어떻게 상태 인지를 말하지 말고 객체에게 무엇을해야하는지 알려 주어야합니다 . 자세한 내용은 여기 , 여기 , 여기여기를 참조하십시오 .

편집 : Alan Kay의 OOP 정의에 대한 매우 훌륭한 설명을 찾았 습니다 .


3

ADT 지지자를 보면 ADT를 OOP가 클래스 (내부, 개인 상태, 제한된 작업 집합 허용)라고 부르는 클래스로 간주하지만 클래스 간 관계 (기본적으로 상속 없음)는 고려되지 않습니다. 요점은 다른 구현으로 동일한 동작을 얻을 수 있다는 것입니다. 예를 들어 집합은 목록, 배열 또는 해시 테이블의 요소 또는 일종의 트리로 구현할 수 있습니다.


2

나는 항상 이런 식으로 이해했다.

  1. ADT는 인터페이스입니다. 이는 사전 및 사후 조건이있을 수있는 메소드, 유형 서명의 모음 일뿐입니다.

  2. 클래스는 ADT에 지정된 메소드에 대한 실제 구현을 제공하여 하나 이상의 ADT를 구현할 수 있습니다 .

  3. 객체는 정적이 아닌 변수의 자체 복사본이있는 클래스 의 인스턴스 입니다.

문헌에서 차이점이 다를 수 있지만 이것이 컴퓨터 과학에서들을 수있는 "표준"용어입니다.

예를 들어, Java에서 CollectionADT, ArrayList클래스 및 연산자를 사용하여 ArrayList객체를 만들 수 있습니다 new.

ADT는 일반적으로 구현이 하나뿐이라는 진술에 대해서는 그렇지 않습니다. 예를 들어, 저장하는 내용에 따라 프로그램에서 트리 기반 및 해시 테이블 기반 사전을 모두 사용할 수 있습니다. ADT를 공유하지만 다른 구현을 사용합니다.


1
기능적 프로그래밍 관점에서 볼 때 ADT에는 클래스에 일반적으로없는 특정 제한이 없습니까?
Raphael

@Raphael 무엇처럼?
jmite

1
이것은 ADT에 대한 일반적인 견해이며 합리적인 근사치입니다. 그러나 내가 이해하는 것처럼 PL 문헌에서 고려되고 공식적으로 정의 된 ADT는 실제로 다소 구체적인 의미를 갖습니다. ADT는 구현 방식이나 데이터 표현 방식이 아니라 데이터에 대한 인터페이스 (어떤 종류의 작업을 수행 할 수 있습니까?) 각 작업의 동작 / 시맨틱 같은 일종의 데이터 구조 사양입니다 . 따라서 Java 인터페이스 (유형 서명이있는 메소드 목록)뿐만 아니라 해당 동작의 사양이기도합니다.
DW

1
예를 들어 Java Collection인터페이스는 ADT가 아니라는 인상을 받았습니다 . 메소드 목록을 제공하지만 의미를 지정하지 않습니다. 집합의 의미를 제공합니까? 멀티 세트 (가방)? 주문한 목록? 지정되지 않은 채로 있습니다. ADT로 계산되는지 잘 모르겠습니다. 그건 내 인상이지만 내 이해가 잘못되었을 수도 있습니다.
DW

내가 강의 슬라이드에서 Java 클래스 (인터페이스조차도 아님)는 ADT로 간주됩니다. . 한편, 인터페이스를 통해 액세스 된 클래스는 객체로 간주되며 인터페이스에 의해 정의 된 메소드는 "메시지"(높은 수준의 의도)입니다. 의도를 통해 객체들이 서로 대화 할 때, 객체의 다른 구현은 서로 "대화"할 수 있습니다.
LMZ
당사 사이트를 사용함과 동시에 당사의 쿠키 정책개인정보 보호정책을 읽고 이해하였음을 인정하는 것으로 간주합니다.
Licensed under cc by-sa 3.0 with attribution required.