基于Pharo Smalltalk的Person类构造方法自动赋值问题求助
问题分析与解决方案
核心问题拆解
你当前的代码存在三个关键问题:
- setter选择器获取错误:
classMethod allSelectorsInProtocol: #'setter'是从类方法的角度获取选择器,但setter是实例方法,应该从类的实例侧获取。 - 方法构建逻辑错误:直接拼接字符串
setter,':',items无法生成有效的消息发送逻辑,Smalltalk需要用perform:来动态调用方法。 - 值与属性不匹配:没有保证setter的顺序和
items中随机值的顺序对应,导致属性赋值混乱。
分步修正方案
1. 修正generateData的类型判断逻辑
原类型判断存在顺序问题(抽象类型会覆盖具体类型),调整为从具体到抽象的判断顺序,同时确保生成的值顺序与Person实例变量顺序一致:
generateData | items typeList | items := OrderedCollection new. "按name、birthDate、lastName的类型顺序定义" typeList := {ByteString. Date. String}. typeList do: [ :type | type == ByteString ifTrue: [ items add: UUID new asString36 ]. type == Date ifTrue: [ items add: (Date fromDays: (1 to: 36000) atRandom) ]. type == String ifTrue: [ items add: UUID new asString36 ]. "按需补充其他类型判断" ]. ^ items
2. 重构构造方法(或新增自动填充构造方法)
新增一个类方法,自动用generateData生成的随机值初始化Person实例,同时动态匹配setter与值:
Person class >> withRandomData | person items setters | person := self new. items := self generateData. "方式1:硬编码setter(适合固定属性的场景)" setters := #(name: birthDate: lastName:). "方式2:动态生成setter(适合属性可能变化的场景)" "setters := self instanceSide instVarNames collect: [ :var | (var, ':') asSymbol ]." "按顺序给实例发送setter消息" setters with: items do: [ :setter :value | person perform: setter with: value ]. ^ person
3. 修复原setter获取逻辑(如果需要动态获取)
如果要从#setter协议中获取选择器,需从类的实例侧获取,同时按实例变量顺序排序:
"正确获取实例侧的setter选择器" setters := (self instanceSide selectorsInProtocol: #setter) sorted: [ :a :b | self instanceSide instVarNames indexOf: (a allButLast asSymbol) < self instanceSide instVarNames indexOf: (b allButLast asSymbol) ]
验证使用
直接调用新构造方法即可生成随机初始化的Person实例:
randomPerson := Person withRandomData. randomPerson inspect. "查看属性是否正确赋值"
内容的提问来源于stack exchange,提问作者Mansour Faouziel
相关产品推荐
相关产品推荐

