2013-04-12 4 views
5

스몰 토크에서 더 나은 반향을 이해하려고합니다. 최신 버전의 Squeak (v4.3)을 사용하고 있습니다. 내 수업 중 하나의 인스턴스로 전송 된 모든 메시지를 가로 채고 싶습니다. 나는 ProtoObject>>withArgs:executeMethod 메서드를 오버라이드 할 수 있다고 가정했으나 Stéphane Ducasse는 성능상의 이유로이 방법을 사용하지 않는다고 설명했습니다 (이것은 내 자신의 답변 요약입니다). 어떤 방법을 무시해야합니까/어떻게 보낸 메시지를 가로 챌 수 있습니까? 코드 수율이 전체 조각을 실행스퀵의 차단 메시지

Object subclass: #C 
    instanceVariableNames: 'i' 
    classVariableNames: '' 
    poolDictionaries: '' 
    category: 'CSE3009'. 

C class compile: 'newWithi: anInt 
    ^(self new) i: anInt ; yourself.'. 

C compile: 'withArgs: someArgs executeMethod: aMethod 
    Transcript show: ''Caught: ''. 
    ^super withArgs: someArgs executeMethod aMethod.'. 

C compile: 'foo: aText 
    Transcript show: aText. 
    Transcript show: i. 
    Transcript cr.'. 

C compile: 'i: anInt 
    i := anInt.'. 

o := C newWithi: 42. 
o foo: 'This is foo: '. 

: 여기

는 내 시도의 코드

This is foo: 42 

나는이 없다 싶을 때 :

Caught: This is foo: 42 
+0

최근 출시 된 Squeak 버전은 4.4입니다. –

답변

5

더있다 그런 방법으로 메시지를 가로 챌 수 있습니다. 우리가 이런 종류의 트릭을하기 위해 일반적으로 사용하는 두 가지 방법이 있습니다.

먼저 doesNotUnderstand :에 응답하는 래퍼 개체를 만들 수 있습니다. 이 객체는 대개 슈퍼 클래스에 대해 nil을 가지므로 Object에서 인스턴스 메서드를 상속하지 않습니다. doesNotUnderstand : 핸들러는 모든 메시지를 대상 객체에 위임합니다. 통화 전후에 코드를 수행 할 수있는 옵션이 있습니다. 원래 객체에 대한 모든 참조는 이제 새로운 "프록시"객체를 가리 킵니다. self에 대한 메시지는 가로 챌 수 없으며 프록시는 자체를 반환하는 객체를 테스트하고 반환 된 객체를 대신 프록시로 변경해야합니다.

두 번째 방법은 Method Wrappers라는 메커니즘을 사용하는 것입니다. 메서드 래퍼를 사용하면 클래스 집합의 모든 메서드를 원래 메서드를 호출하기 전후에 다른 작업을 수행하는 메서드로 바꿀 수 있습니다. 이 접근법은 상당히 명백한 결과를 제공 할 수 있으며 자기에게 보내는 메시지를 포함하여 모든 메시지를 가로 챌 수 있습니다.

MethodWrappers는 VisualWorks 및 VASmalltalk에서 사용할 수 있습니다. Squeak과 Pharo에도 사용할 수 있지만 긍정적이지는 않습니다.

+1

Squeak 또는 Pharo에 대한 여러 'MethodWrapper'구현이 있습니다 – Tobias

+0

답장을 보내 주셔서 감사합니다. 그러나 조금 놀랐습니다. 리플렉션을 통해 메소드 호출의 의미를 변경할 수 있습니까? (그렇기 때문에'ProtoObject >> withArgs : executeMethod :'를 오버라이드 할 수 있다고 생각한 이유입니다. 새로운 클래스 메소드를 오버라이드 할 수있는 것과 비슷합니다. –

+0

'doesNotUnderstand :'를 사용하는 솔루션이 작동하는 것처럼 보입니다. 왜냐하면 언어는 타입이없고'MethodWrapper' (그리고 다른 [ObjectTracer] (http : // stackoverflow.com/questions/888900/in-squeak-how-to-wrap-every-method-send))는'doesNotUnderstand : '를 사용하여 솔루션을 구현 한 것입니다. –

1

세 가지 주요 기술은 다음과 같습니다

  • 동적 프록시
  • 모든 가능한 접근 방식의 좋은을 비교 한 메서드 래퍼
  • 바이트 코드 계측

, "Evaluating Message Passing Control Techniques in Smalltalk"를 보라 Stephane Ducasse (당신은 이미 그를 알아, 분명히).

또한 관심있는 내용은 F. Rivard의 "Smalltalk: A Reflective Langauge"이며, 바이트 코드 재 작성을 사용하여 사전 및 사후 조건을 구현하는 방법을 보여줍니다. 이것은 또한 차단의 한 형태입니다.

+0

감사합니다. @ewernli, 저는 이미 그것을 읽었지만 제 문제에 직접적인 해결책을 제시하지는 않습니다 ... –