2016-04-27 44 views
2

构造函数我想实现的Pharo小类,所以我这样做:使得在菲罗或Smalltalk中

Object subclass: #Person 
    instanceVariableNames: 'name age' 
    classVariableNames: '' 
    category: 'Test' 

,我想模拟一个构造函数,因此我做了类似下面的方法:

newName:aName newAge:aAge 
    "comment stating purpose of message" 

    name:=aName. 
    age:=aAge. 
    ^self. 

但是当我想从菲罗操场这样称呼它:

objPerson:=Person newName:'Carl' newAge: 10. 

它是没有t被Pharo识别,我做错了什么?

回答

6

表达式Person newName: 'Carl' newAge: 10是类对象Person的消息。所以你必须在Person的课堂上实现它。

您的代码需要进行调整这样

Person class >> newName: aName newAge: anAge 
    | person | 
    person := self new. 
    person name: aName. 
    person age: anAge. 
    ^person 

注意,在上面self代码指的是类,因为该方法是在类的一面。但由于personPerson的实例,因此必须在实例端定义消息name: aNameage: anAge

因此,在该实例的一面,你需要添加两个设置方法:

Person >> name: aString 
    name := aString 

Person >> age: anInteger 
    age := anInteger 

有了这三个方法,你应该能够运行你的例子。


的编码风格的一些补充意见:

首先,我会选择为“构造”方法的不同选择(在Smalltalk我们称之为“实例创建”的方法)。例如,

Person class >> named: aString age: anInteger 
    ^self new name: aString; age: anInteger 

其次,有没有必要使用新创建的实例的临时person作为表达self new已经指这样一个实例。

最后,请注意在

^self new name: aString; age: anInteger 

使用级联语法,这意味着该消息age: anInteger将被发送到同一个接收器name: aString,在这种情况下,恰好是由self new返回的新实例。

3

虽然一般来说,我同意莱安德罗的回答,它揭示访问者的私人财产。

肯特·贝克在他的Smalltalk的最佳实践模式(我强烈建议),建议使用set作为实例侧构造一个前缀,如:

"add to class side to 'instance creation' protocol" 
Person>>class name: aName age: anAge 
    ^self new 
     setName: aName age: anAge; 
     yourself 

"add to instance side to 'initialization' protocol" 
Person>>setName: aName age: anAge 
    name := aName. 
    age := anAge. 

这样,您就可以控制无论你是否会暴露这些属性。

或者你可以坚持你原来的命名,只是添加new,你忘了。

objPerson := Person new newName:'Carl' newAge: 10.

+0

好点。但是,我会使用'#name:age:'选择器而不是'#setName:age:'。其他语言需要在设置者和获取者之前加上'set'或'get',因为他们没有其他的方式来区分它们。在Smalltalk中,冒号是选择器的一部分,然后使用这些前缀变得多余。 –

+0

@LeandroCaniglia正是它的前缀的原因 - 区分它与普通的setter(没有前缀)。你不打算再次调用这个方法。 –

+0

我重视拥有实例端构造函数的想法,以及将它们与常规setter进一步区分的想法。但是,我更喜欢从方法的分类中传达差异,而不是将'set'附加到选择器上。 –