我认为我的问题主要是语法,但这可能是我对类层次结构的整体理解。基本上,这是一个Deck类,其数组中填充有Card对象,Card是Deck的子类,因此Deck应该能够使用Card的块和方法,对吗?如果是的话,我会搞砸语法,以尝试调用它。我正在使用嵌套的while循环来填充数组,但是我希望Card对象的每个实例都具有该卡的外观和等级,而不是仅打印“ A Card”。我离开了我尝试使Card对象成为另一个尺寸为2的数组以容纳Suit和Rank的位置,但是我的gst编译器说它期望一个“对象”,所以显然我在做错什么。我粘贴了代码,这样您就可以了解我在说什么。除了块调用之外,它还用空白卡对象填充了大小为52的数组,因此Deck类的其余部分基本上可以正常工作。
"The Deck object class is a deck of 52 Card objects. "
Object subclass: Deck [
| Content |
<comment: 'I represent of Deck of Cards'>
Deck class >> new [
<category: 'instance creation'>
| r |
r := super new .
Transcript show: 'start ' .
r init .
^r
]
init [
<category: 'initialization'>
|a b c|
Content := Array new: 52 .
a := 1 .
c := 1 .
[a <= 4] whileTrue:[
b := 1 .
[b <= 13] whileTrue:[
|card|
card := Card new .
Card := Array new: 2 . "This is where I'm trying to use the Card class blocks to make the Card objects have Rank and Suit"
Card at: 1 put: Card setRank: b| . "and here the rank"
Card at: 2 put: Card getSuit: a| . "and the suit"
Content at: c put: card .
b := b + 1 .
c := c + 1 .
].
a := a + 1 .
].
Content printNl .
]
] .
"The Card object has subclass Suit and a FaceValue array of Suit and Rank. "
Object subclass: Card [
| Suit Rank |
<comment: 'I represent a playing Card' >
init [
<category: 'initialization'>
Suit := Club .
Rank := 1 .
Transcript show: 'nCard ' .
^super init
]
getSuit: suitVal [
suitVal = 1 ifTrue: [Suit := Club] .
suitVal = 2 ifTrue: [Suit := Diamond] .
suitVal = 3 ifTrue: [Suit := Heart] .
suitVal = 4 ifTrue: [Suit := Spade] .
^Suit
] "getSuit"
setRank: rankVal [
Rank := rankVal .
^Rank
]
]
z := Deck new .
答案 0 :(得分:3)
编辑一次-由于联邦调查局的评论
欢迎来到。
免责声明:我使用的是Smalltalk / X-jv分支,该分支与gnu-smalltalk不同,因此它不是smalltalk,所以我不是gnu-smalltalk专家。
我会指出一些我发现的不足之处。有太多需要指出的地方。我给你一些一般的想法。
我通常不建议使用a
,b
,c
... z
作为变量。如果过了一段时间再返回代码,您将无法理解。
对于变量,请使用小写字母,例如content
而不是Content
。首先
大写字母保留用于全局变量。在您的用例中,这将是一个类名(不要混合使用)。
如果要创建新实例,请像下面这样使用它:aCard := Card new.
不要在#init
(初始化)方法中创建整个应用程序逻辑!您应该使用小的可读方法破坏代码。
您的init应该遵循以下原则:
Deck extend [
init [
<category: 'initialization'>
content := Array new: 52.
Transcript show: 'Initializing Deck...'.
]
]
将使用实例变量#init
创建一个content
方法。不要忘记为变量创建访问器。阅读guide了解gnu-smalltalk和创建实例方法。
您应该在whileTrue:
循环上有注释。为什么有人要猜测限制的原因?
[a <= 4] whileTrue:[
b := 1 .
[b <= 13] whileTrue:[
...
有充分的理由重新定义new
消息。 Transcript
消息可以是ini init
:
Deck class >> new [
<category: 'instance creation'>
| r |
r := self new .
Transcript show: 'start '.
r init .
^r
]
您为什么要重新定义新的?如果您有一个Object subclass:
对象,那么它
已经了解new
消息。
在代码的底部,您有z := Deck new.
(我建议使用例如myDeck := Deck new.
)。如果要运行初始化,只需执行myDeck init
。
您为什么在Card >> init
返回^super init
?也许您想做第一行super init
(读取\加载超类init)然后返回^ self
?很难说。
Suit := Club .
是什么意思?您是否正在以某种方式创建新对象? (缺少#new
条消息)。您是否在尝试串音?然后应该是suit := 'Club'.
。 (所有Sunit
变量分配都一样)。
更多的只是从水晶球中读取。尝试阅读有关Smalltalk的更多信息,希望我的技巧对您有所帮助。
答案 1 :(得分:2)
一些更正:您不调用块,而是调用方法。
您提交的代码中唯一的块是whileTrue:的参数,并且是方法专用的(不能从外部访问)。
这种混乱不是您的错。这是由于此文件格式用于描述方法的块符号引起的。就个人而言,我不喜欢它,我发现它比实用更令人困惑(除了为了看起来更主流的语言,向基于文件的语言致敬之外)。
那么您如何调用方法?您通过发送消息来做到这一点,没有其他方法。您所能做的就是发送一条消息。 Smalltalk是面向消息的。消息一直传下来。
当接收到消息时,该对象将在其类方法字典中查找消息选择器。如果不存在,它将在超类中进行查找,等等。但这是对象本身的事。
因此,最后,您并没有真正考虑调用方法,因为不同的对象可以使用不同的方法来响应相同的消息。您必须考虑将任务委派给特定对象,即消息和相关合同。
那合同是什么?您希望一张牌具有西服(俱乐部,黑桃,...)和等级(1到13)。因此,您使用这两个实例变量创建了Card类。到目前为止,一切都很好。
然后,您要创建52张卡片以填充卡片组。那就是实例化Card类。你是怎样做的?您已将消息new
发送到Card类。您可以创建一个更合适的类消息,该消息将充当Card构造函数,并给出一个西装和一个等级。
那将是
Card class >> newWithSuit: aSuit rank: anInteger
[<category: 'instance creation'>
^self basicNew setSuit: aSuit rank: anInteger ]
setSuit: aSuit rank: anInteger
[<category: 'private'>
suit := aSuit.
rank := anInteger ]
然后,您不需要定义单个的setter(在代码中为getSuit:
和setRank:
),因为您可能不希望以后更改这些属性,除非在构造时。这就是为什么我通常更喜欢一个归类为“私人”的二传手。那只是一个约定,但这就是我们在Smalltalk中定义合同的方式,是通过一组非正式约定,以及方法和类注释(以及SUnit TestCase,尤其是如果您采用测试驱动的设计)。
您决定将等级编码为1到13之间的整数。没关系。 但是,您还必须决定如何代表诉讼。您的代码尚不清楚,因为混合使用了整数(1到4)和未声明的变量(Club,Spade等)。这些是全局变量吗?
然后,您不必编码那些西服并在大小为2的数组中排名,由于所有这些数据已经包含在Card对象中,因此绝对没有必要。因此,您需要在甲板上填充:
content at: deckRank put: (Card newWithSuit: suitNumber rank: rankNumber).
注意括号:您将带有两个参数at:put:
的消息content
发送到deckRank
,而另一条消息返回的值发送了(Card newWithSuit: suitNumber rank: rankNumber)
,我们希望这是一个正确初始化的Card实例。
在您提供的代码Card at: 1 put: Card setRank: b
中,您向带有三个参数的类at:put:setRank:
发送消息Card
,该参数包含3个参数,即整数常量1,类Card
和所指向的对象通过变量b
。那可能不是你的意图。在|
之后还有一个b
栏,对我来说似乎不太正确。条形图用于描绘临时变量,或将块自变量与块内块指令分开,或者也可以是二进制消息,但在这种情况下,需要一个自变量(每条二进制消息,例如+-* /都有一个接收器和一个自变量)。
希望我能给您一些有用的提示,但也许您必须阅读并应用一些分步的Smalltalk教程才能更好地了解这些基本概念。