OO에서 전달되는 메시지는 무엇입니까?


35

저는 주로 C ++, C # 및 Java에서 OO 프로그래밍을 공부했습니다. 캡슐화, 상속 및 다형성에 대한 이해 (이 사이트에서 많은 질문을 읽음)를 잘 알고 있다고 생각했습니다.

여기에 팝업되는 것으로 보이는 것은 "메시지 전달"이라는 개념입니다. 분명히 이것은 오늘날의 주류 언어로 OO 프로그래밍하는 동안 사용되지 않지만 Smalltalk에서 지원되는 것입니다.

내 질문은 :

  • 메시지 전달이란 무엇입니까? (누군가 실용적인 예를 들어 줄 수 있습니까?)
  • C ++, C # 또는 Java에서이 "메시지 전달"을 지원합니까?

4
나는 얼마 전에 SO에 대해이 질문에 대답했습니다 : stackoverflow.com/a/3104741/10259
Frank Shearar

1
Wikipedia 기사 를 읽었습니까 ?
yannis

4
겸손한 의견으로 Objective-C는 주류 언어가 될 것입니다. 적어도 C #만큼.
mouviciel

나는 내 경험에서 "주류"언어를 언급하고 있다는 것에 동의한다
Tom

멤버 함수 호출은 메시지 전달의 한 구현입니다. 전달 된 메시지는 기능 이름으로 식별되며 매개 변수의 정보를 포함합니다. 늦은 바인딩은 수신 클래스가 다른 클래스와 다른 방식으로 동일한 메시지를 처리 ​​할 수 ​​있도록합니다. 그것은 Simula의 제작자가 의도 한 것이 아니며 많은 사람들이 메시지 전달 및 상태 전달 (이유가 있음)이 메시지 전달을하는 것이 Simula를 차별화시키는 핵심 요소라고 주장하지만 회원 함수 호출은 여전히 ​​본질적으로 동일합니다. 일.
Steve314

답변:


60

메시지 전달이란 무엇입니까? (누군가 실용적인 예를 들어 줄 수 있습니까?)

메시지 전달은 단순히 프로그램 실행의 기본 메커니즘이 서로 메시지를 보내는 객체라는 것을 의미합니다. 중요한 점은 이러한 메시지의 이름과 구조가 소스 코드에서 미리 고정되어 있지는 않으며 추가 정보가 될 수 있다는 것입니다. Alan Kay가 원래 "객체 지향 프로그래밍"으로 구상 한 것의 중요한 부분입니다.

C ++, C # 또는 Java에서이 "메시지 전달"을 지원합니까?

이 언어는 메소드 호출을 통해 전달되는 제한된 버전의 메시지를 구현합니다. 전송할 수있는 메시지 세트가 클래스에 선언 된 메소드로 제한되므로 제한됩니다. 이 접근 방식의 장점은 매우 효율적으로 구현할 수 있으며 매우 상세한 정적 코드 분석 (코드 완성과 같은 모든 종류의 유용한 이점이 있음)을 가능하게한다는 것입니다.

반대로, "실제"메시지 전달을 구현하는 언어는 종종 메시지 핸들러를 구현하는 편리한 방법으로 메소드 정의를 갖지만, 클래스가보다 유연한 메시지 핸들러를 구현하여 오브젝트가 임의의 이름으로 "메소드 호출"을받을 수있게합니다 (고정되지 않음) 컴파일 타임에).

이 개념의 힘을 보여주는 Groovy :

def xml = new MarkupBuilder(writer)
xml.records() {
  car(name:'HSV Maloo', make:'Holden', year:2006) {
    country('Australia')
    record(type:'speed', 'Production Pickup Truck with speed of 271kph')
  }
}

이 XML을 생성합니다 :

<records>
  <car name='HSV Maloo' make='Holden' year='2006'>
    <country>Australia</country>
    <record type='speed'>Production Pickup Truck with speed of 271kph</record>
  </car>
</records>

그 주 records, car, countryrecord구문 메소드 호출하지만에 정의 된 이름의 방법이 없습니다 MarkupBuilder. 대신, 모든 메시지를 승인하고 메시지 이름을 XML 요소의 이름으로, 매개 변수를 속성으로, 클로저를 하위 요소로 해석하는 범용 메시지 핸들러가 있습니다.


정답에 +1. 코드 예제에 허용됩니다. 도와 주셔서 감사합니다 :)
Tom

간단 sendMessage(property_name, Array of arguments)하고 getMessage(property_name, Array of arguments)정적 인 언어로 간단하게 구현할 수 없었 습니까?
Pacerier

1
@Pacerier : 물론, 두 가지 방법의 단점을 결합한 것입니다. 타입 안전성을 잃어 버리고 여전히 "sendMessage"를 사용하여 모든 곳에서 코드를 오염시킬 수 있으므로 우아한 구문을 얻을 수 없습니다.
Michael Borgwardt

Groovy 예제에서 메시지 핸들러가 메소드 호출이 아니라 메시지를 수신하고 있다고 말하는 것이 더 정확합니까? 처음에는 "method call"이라는 문구를 따옴표로 묶지 만 마지막 문장에서는 "messages"가 아니라 " 모든 메소드를 받아들입니다"라고 말합니다 .
Adam Zerner

@ 아담 제너 : 당신이 맞아, 내가 고쳤다.
Michael Borgwardt

28

메시지 전달은 한 객체가 다른 객체 (또는 잠재적으로 자체)가 무언가를 수행하도록 OO 코드의 요구를 처리하는 다른 방법입니다.

C ++ 방식에서 유래 한 대부분의 현대 언어에서는 메소드 호출을 사용하여이를 수행합니다. 이 경우, 호출 된 객체 (클래스 정의를 통해)는 어떤 메소드 호출을 받아들이는지에 대한 큰 목록을 작성한 다음 호출 객체의 코더가 단순히 호출을 작성합니다.

public void doSomething ( String input )
...
other_object.dosomething ( local )

정적으로 유형이 지정된 언어의 경우 컴파일러는 호출되는 항목의 유형을 확인하고 메소드가 선언되었는지 확인할 수 있습니다. 동적으로 입력 된 언어의 경우 런타임에 수행됩니다.

그러나 본질적으로 발생하는 일은 변수 묶음이 특정 코드 블록으로 전송된다는 것입니다.

메시지 전달

메소드 대신 메시지 전달 언어 (예 : Objective C)에는 수신자가 있지만,이를 정의하고 호출하는 방식은 거의 동일합니다. 차이점은 처리 방식입니다.

메시지 전달 언어에서 컴파일러 사용자가 호출 한 수신자가 존재하는지 확인할 있지만 최악의 경우 해당 수신자가 확실하지 않다는 경고가 표시됩니다. 이는 런타임에 수신 객체의 코드 블록이 변수 묶음과 호출하려는 수신자의 서명을 모두 전달하여 호출되기 때문입니다. 그런 다음 해당 코드 블록은 수신자를 찾아서 호출합니다. 그러나 수신자가 존재하지 않으면 코드는 단순히 기본값을 반환합니다.

결과적으로 C ++ / Java-> Objective C에서 이동할 때 발견되는 이상한 점 중 하나는 컴파일 타임 유형에 선언되지 않았고 존재하지 않는 객체에서 "메소드를 호출 할 수 있음"을 이해하는 것입니다. 런타임 유형 ... 및 호출로 인해 예외가 발생하지 않지만 실제로 결과가 전달됩니다.

이 접근법의 장점은 서브 클래스 계층 구조를 평평하게하고 인터페이스 / 다중 상속 / 오리 유형에 대한 대부분의 요구를 피한다는 것입니다. 또한 객체가 수신자가없는 무언가를하도록 요청 받았을 때 객체가 기본 동작을 정의 할 수있게합니다 (일반적으로 "내가하지 않으면 요청을이 다른 객체로 전달"). 또한 Java와 같이 정적으로 유형이 지정된 언어를 통해 특히 콜백 (예 : UI 요소 및 시간 초과 이벤트)에 대한 링크를 단순화 할 수 있습니다 (따라서 내부 클래스에서 "actionPerformed"메소드를 호출하는 대신 버튼을 사용하여 수신자 "runTest"를 호출 할 수 있음) "RunTestButtonListener").

그러나 개발자가 생각하는 호출이 올바른 유형의 올바른 객체에 있고 올바른 매개 변수를 올바른 순서로 전달한다는 것은 개발자의 추가 검사가 필요한 것으로 보입니다. 컴파일러는 경고하면 런타임에 완벽하게 실행됩니다 (기본 응답 만 반환). 추가 조회 및 매개 변수 전달로 인한 성능 저하도있을 수 있습니다.

요즘에는 동적으로 유형이 지정된 언어가 OO로 전달 된 메시지의 문제점을 줄이면서 많은 이점을 얻을 수 있습니다.


1
나는이 답변을 좋아합니다. 차이점과 그 의미를 설명합니다.
HappyCat

@Gavin, PHP와 Javascript의 동적 메소드 핸들러정확히 동일 합니까?
Pacerier

11

메시지 전달 아키텍처는 각 구성 요소가 다른 구성 요소와 독립적이며 시스템간에 데이터를 전달하는 일반적인 메커니즘을 갖춘 시스템입니다. 메쏘드 호출을 메시지 전달의 한 형태로 간주 할 수 있지만 그렇게하는 것은 실용적이지 않으며 문제를 혼동합니다. 잘 정의 된 메소드가있는 클래스와 해당 메소드를 호출하는 일부 코드가있는 경우 전체 항목을 함께 컴파일하여 코드와 오브젝트를 결합해야하기 때문입니다. 메시지가 전달되고 컴파일러가 정확성을 강화하고 있지만 분리 된 시스템의 유연성을 많이 잃어 감에 따라 메시지가 얼마나 가까이 있는지 확인할 수 있습니다.

메시지 전달 아키텍처를 사용하면 런타임에 개체를 추가 할 수 있으며 메시지를 하나 이상의 개체로 리디렉션 할 수없는 경우가 많습니다. 따라서 'data x is updated'메시지를 시스템에로드 된 모든 객체에 브로드 캐스트하는 코드를 가질 수 있으며 각 객체는 해당 정보로 원하는 작업을 수행 할 수 있습니다.

이상한 예가 웹입니다. HTTP는 메시지 전달 시스템입니다. 명령 동사와 '데이터 패킷'을 서버 프로세스에 전달합니다. (예 : GET http : \ myserver \ url) 브라우저 나 웹 서버는 전송하는 데이터 나 전송 위치에 대해 신경 쓰지 않습니다. 서버는이 데이터를 다른 '패킷'데이터를 패키징하는 코드로 전달하여 사용자에게 다시 보냅니다. 이 시스템의 어떤 구성 요소도 다른 작업이나 그 작업에 대해 전혀 알지 못하며 메시지 통신에 사용 된 프로토콜 만 알면됩니다.


@gbjbannb, 의사 코드 설명이 필요합니다 ....
Pacerier
당사 사이트를 사용함과 동시에 당사의 쿠키 정책개인정보 보호정책을 읽고 이해하였음을 인정하는 것으로 간주합니다.
Licensed under cc by-sa 3.0 with attribution required.