So, I still don't know if there might not be a much easier way to do it, but I'm fine with what I've dreamt up today. If I want to add a new instance variable to a class, including all accessors, I call this from a workspace:
ManyManyRelation addPropertyName: #oneLot
.And if I want to initialize the property to something, I use this:
ManyManyRelation addPropertyName: #otherLot lazyInitializeWith: [Set new]
.The following method goes to the instance side of Class:
addPropertyName: aSymbol
self addInstVarName: aSymbol.
self compileAccessorsFor: aSymbol
And then:
compileAccessorsFor: aSymbol
"Compile instance-variable accessor methods
for the given variable name "
self compileSilently: aSymbol asString , '
^ ' , aSymbol classified: 'access'.
self compileSilently: aSymbol asString , ': anObject'
, aSymbol , ' := anObject' classified: 'access'
You can now call something like
ManyManyRelation addPropertyName: #oneLot
, and it adds an instance variable to ManyManyRelation, including both accessors.Let's push it one step further. Hooking into initialize really doesn't feel right––if objects are about modelling the real world, then what exactly corresponds to object initialization? While still not being optimal, the following creates lazy initizers in the accessors.
The following two methods go as instance methods into Class:
addPropertyName: aSymbol lazyInitializeWith: aBlock
self addInstVarName: aSymbol.
self compileAccessorsFor: aSymbol lazyInitializeWith: aBlock
compileAccessorsFor: aSymbol lazyInitializeWith: aBlock
| initializeCommand decompileString |
decompileString := aBlock decompileString.
initializeCommand := decompileString copyFrom:
2 to: decompileString size - 1.
self compileSilently: aSymbol asString , '
^ ' , aSymbol , ' ifNil: [ ' , aSymbol ,
' := ' , initializeCommand , ']' classified: 'access'.
self compileSilently: aSymbol asString , ': anObject
' , aSymbol , ' := anObject' classified: 'access'
You use it by calling
ManyManyRelation addPropertyName: #otherLot lazyInitializeWith: [Set new]
.By the way, I would refrain from using
(CreateAccessorsForVariableRefactoring variable: #hasMany class: OneManyRelation classVariable: false) execute
, which is what happens when you create accessors using OmniBrowsers, the reason being it behaves strangely when the object already responds to a message, most typically like name.
No comments:
Post a Comment
Note: Only a member of this blog may post a comment.