2016-09-09 3 views
1

Представьте меня есть метод, какПолучить приемник цепи из контекста отправителя

someMethod 

^instVar class getProperty 

Могу ли я каким-то образом реализовать метод getProperty таким образом

getProperty 

    thisContext sender ... 

, чтобы получить объект, к которому class в настоящее время послал? I'e значение instVar, но не зная, что это переменная экземпляра, возможно, это параметр или литерал в некоторых других случаях.

+1

Что вы пытаетесь сделать? –

+0

Что Леандро сказал. Разве это не ваш метод, т. Е. Вы не знаете, является ли «instVar» переменной экземпляра? Вы хотите сделать какую-то форму IoC? –

ответ

1

Я не вижу ничего очевидного, instVar больше не находится в стеке выполнения, он заменяется возвращаемым значением message 'class'.

Возможно, вы могли бы обмануть и измерить всех отправителей цепи «класс getProperty», чтобы сделать что-то особенное, например, заменить «MyAnalyzer getClassPropertyOf: instVar». Это звучит как зло.

0

Можете ли вы реорганизовать someMethod следующим образом?

someMethod 

^instVar class getPropertyOf: instVar 
+0

К сожалению нет, поэтому я хочу пересекать контексты, так как я не могу изменить существующий код, и в системе есть много таких способов использования. – Uko

0

Вы можете инструмент слоты вернуть обертку или прокси-сервер при ответе на class. Прокси-сервер будет знать объект, хранящийся в слоте.

+0

Это работает, если instVar не является переменной экземпляра? –

+0

Нет, к сожалению, нет. Я думал, что я упомянул об этом в любом случае, если переменные экземпляра всегда задействованы. –

1

Это ужасно и, вероятно, не будет работать во всех случаях, но может дать вам отправную точку, если вам абсолютно необходимо это сделать (и также является хорошей демонстрацией уровня отражательной способности, возможного в Smalltalk):

getProperty 

    | sender message receiver | 

    sender := thisContext sender. 
    message := sender method abstractBytecodeMessageAt: (sender pc - 3). 

    message selector = #pushReceiverVariable: ifTrue: [receiver := sender receiver instVarAt: (message arguments first + 1)]. 
    message selector = #pushTemporaryVariable: ifTrue: [receiver := sender tempAt: (message arguments first + 1)]. 
    message selector = #pushConstant: ifTrue: [receiver := message arguments first]. 

    receiver isNil ifTrue: [self error: 'unknown']. 

    ^receiver 
Смежные вопросы