Smalltalk 如何在超类方法中从子类调用块?
我认为我的问题主要是语法,但可能是我对类层次结构的总体理解。基本上它是一个卡片类,有一个充满卡片对象的数组,卡片是卡片的一个子类,所以卡片应该能够使用卡片的块和方法,对吗?如果是这样的话,我在尝试调用它时就把语法搞乱了。我使用嵌套的while循环来填充数组,但我希望Card对象的每个实例都具有该卡的套色和等级,而不仅仅是打印一张卡。我离开的地方,我试图使卡对象的另一个数组大小为2,以容纳西装和排名,但我的gst编译器说,它期待一个对象,所以很明显,我做错了什么。我粘贴了我的代码,所以你可以看到我在说什么。除了块调用之外,它正在用空白卡片对象填充一个大小为52的数组,因此Deck类的其余部分基本上可以工作Smalltalk 如何在超类方法中从子类调用块?,smalltalk,gnu-smalltalk,Smalltalk,Gnu Smalltalk,我认为我的问题主要是语法,但可能是我对类层次结构的总体理解。基本上它是一个卡片类,有一个充满卡片对象的数组,卡片是卡片的一个子类,所以卡片应该能够使用卡片的块和方法,对吗?如果是这样的话,我在尝试调用它时就把语法搞乱了。我使用嵌套的while循环来填充数组,但我希望Card对象的每个实例都具有该卡的套色和等级,而不仅仅是打印一张卡。我离开的地方,我试图使卡对象的另一个数组大小为2,以容纳西装和排名,但我的gst编译器说,它期待一个对象,所以很明显,我做错了什么。我粘贴了我的代码,所以你可以看到我
"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 .
编辑一次-由于fede s.的评论
欢迎来到SO
免责声明:我使用的Smalltalk/X-jv分支与gnu Smalltalk不同,所以我不是gnu Smalltalk专家
我会指出我发现的一些不足之处。有太多的东西要指出。我会给你一些大概的想法
我一般不建议使用a,b,c。。。z作为变量。如果您稍后返回代码,您将无法理解它
对于变量,请使用类似小写的内容,而不是内容。第一
大写字母保留给全局变量。在您的用例中,这将是一个类名,不要混用它
如果要创建一个新实例,请按如下方式使用:aCard:=Card new
不要在init initialize方法中创建整个应用程序逻辑!您应该将代码分解为小的、可读的方法
您的init应该沿着以下几行进行查看:
Deck extend [
init [
<category: 'initialization'>
content := Array new: 52.
Transcript show: 'Initializing Deck...'.
]
]
有充分的理由重新定义新消息。抄本消息可以是ini init:
你为什么要重新定义新概念?如果您有一个对象是对象子类:那么
已经理解了新的信息
在代码的底部有z:=Deck new。我建议使用例如myDeck:=Deck new。。如果您想运行initialize,只需执行myDeck init
为什么您在Card>>init返回^super init?也许您想执行第一行超级初始化读取\加载超类初始化,然后返回^self?很难说
西服:=俱乐部。这是什么意思?您是否正在以某种方式创建一个新对象?缺少新消息。你是在试着解开一根绳子吗?它应该是suit:=“俱乐部”。然后所有Sunit变量分配也是如此
更多的是阅读水晶球。尝试阅读更多有关Smalltalk的信息,我希望我的提示能对您有所帮助。编辑一次-由于fede s.的评论
欢迎来到SO
免责声明:我使用的Smalltalk/X-jv分支与gnu Smalltalk不同,所以我不是gnu Smalltalk专家
我会指出我发现的一些不足之处。有太多的东西要指出。我会给你一些大概的想法
我一般不建议使用a,b,c。。。z作为变量。如果您稍后返回代码,您将无法理解它
对于变量,请使用类似小写的内容,而不是内容。第一
大写字母保留给全局变量。在您的用例中,这将是一个类名,不要混用它
如果要创建一个新实例,请按如下方式使用:aCard:=Card new
不要在init initialize方法中创建整个应用程序逻辑!您应该将代码分解为小的、可读的方法
您的init应该沿着以下几行进行查看:
Deck extend [
init [
<category: 'initialization'>
content := Array new: 52.
Transcript show: 'Initializing Deck...'.
]
]
有充分的理由重新定义新消息。抄本消息可以是ini init:
你为什么要重新定义新概念?如果您有一个对象是对象子类:那么
已经理解了新的信息
在代码的底部有z:=Deck new。我建议使用例如myDeck:=Deck new。。如果您想运行initialize,只需执行myDeck init
为什么您在Card>>init返回^super init?也许您想执行第一行超级初始化读取\加载超类初始化,然后返回^self?很难说
西服:=俱乐部。这是什么意思?您是否正在以某种方式创建一个新对象?缺少新消息。你是在试着解开一根绳子吗?它应该是suit:=“俱乐部”。然后所有Sunit变量分配也是如此
更多的是阅读水晶球。尝试阅读更多关于Smalltalk的内容,我希望我的提示能对您有所帮助。一点更正:您不调用块,而是调用方法 您提交的代码中唯一的块是whileTrue:的参数,并且对于无法从外部访问的方法是私有的 这种混乱不是你的错。这是由于该文件格式用于描述方法的块表示法。就个人而言,我不喜欢它,我觉得它更混乱 除了看起来更像主流语言之外,这是对基于文件的语言的赞扬 那么如何调用一个方法呢?你通过发送信息来实现,没有其他方法。你所能做的就是发送一条消息。Smalltalk是面向消息的。一路下来都是信息 接收消息时,对象将在其类方法字典中查找消息选择器。如果没有,它将在超类中查找,等等。。。但那是物体自己的事 因此,在最后,您并不真正考虑调用方法,因为不同的对象可以使用不同的方法响应相同的消息。您必须考虑将任务委托给专门化对象,即消息和相关契约 那么合同是什么?你想要一张有西服俱乐部的卡片,斯派德。。。排名从1到13。因此,您使用这两个实例变量创建了一个Card类。到目前为止,一切顺利 然后你要创建52张牌来填充牌组。这是对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 ]
请注意括号:您将消息发送到:put:to content,并使用两个参数deckRank和另一个消息发送卡newWithSuit:suitNumber rank:rankNumber返回的值,我们希望它是一个正确初始化的卡实例
在您提供的代码Card at:1 put:Card setRank:b中,您在:put:setRank:向类Card发送一条消息,其中包含3个参数:整数文本1、类Card和变量b指向的对象。那可能不是你的意图。在b后面还有一个条,我觉得它的语法不太正确。条形图用于描绘临时变量,或将块参数与块内的块指令分开,也可以是二进制消息,但在这种情况下需要一个参数每个二进制消息(如+-*/)都有一个接收器和一个参数
我希望我给了你一些有用的提示,但也许你必须阅读并应用一些循序渐进的Smalltalk教程来更好地了解这些基本概念。一点更正:你不调用块,而是调用方法 您提交的代码中唯一的块是whileTrue:的参数,并且对于无法从外部访问的方法是私有的 这种混乱不是你的错。这是由于该文件格式用于描述方法的块表示法。就我个人而言,我不喜欢它,我发现它更令人困惑而不是有用,只是为了看起来更像主流语言,这是对基于文件的语言的赞扬 那么如何调用一个方法呢?你通过发送信息来实现,没有其他方法。你所能做的就是发送一条消息。Smalltalk是面向消息的。一路下来都是信息 接收消息时,对象将在其类方法字典中查找消息选择器。如果没有,它将在超类中查找,等等。。。但那是物体自己的事 因此,在最后,您并不真正考虑调用方法,因为不同的对象可以使用不同的方法响应相同的消息。您必须考虑将任务委托给专门化对象,即消息和相关契约 那么合同是什么?你想要一张有西服俱乐部的卡片,斯派德。。。排名从1到13。因此,您使用这两个实例变量创建了一个Card类。到目前为止,一切顺利 然后你要创建52张牌来填充牌组。这是对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 ]
请注意括号:您将消息发送到:put:to content,并使用两个参数deckRank和另一个消息发送卡newWithSuit:suitNumber rank:rankNumber返回的值,我们希望它是一个正确初始化的卡实例
在您提供的代码Card at:1 put:Card setRank:b中,您在:put:setRank:向类Card发送一条消息,其中包含3个参数:整数文本1、类Card和变量b指向的对象。那可能不是你的意图。在b后面还有一个条,我觉得它的语法不太正确。条形图用于描绘临时变量,或将块参数与块内的块指令分开,也可以是二进制消息,但在这种情况下需要一个参数每个二进制消息(如+-*/)都有一个接收器和一个参数
我希望我给了你一些有用的提示,但也许你必须阅读并应用一些循序渐进的Smalltalk教程,以便更好地了解这些基本概念。仅此而已
澄清一些事情,我非常确定我希望卡片组中充满卡片对象,因为这个项目要求我使用一些规则操纵卡片,根据颜色更改卡片的等级/套装。因此,我认为保持这种结构将使以后更容易做到这一点。否则,我可以用字符填充数组,使其看起来像卡片,但这样就不会是真正的卡片对象。卡不应该是卡组的子类,因为卡不是卡组,它只是卡组的一个元素。为了澄清一些事情,我非常确定我希望卡组充满卡对象,因为这个项目要求我使用一些规则操纵卡,根据颜色更改卡的等级/适合度。因此,我认为保持这种结构将使以后更容易做到这一点。否则,我可以用字符填充数组,使其看起来像卡片,但这样就不会是真正的卡片对象。卡不应该是牌组的子类,因为卡不是牌组,它只是它的一个元素,只是一个吹毛求疵的东西。Afaik,按照惯例,大写字母通常用于全局,其中类名是最扩展的用例。转录本iirc是一个全局实例,Smalltalk通常是SystemDictionary的唯一实例,还有一些其他实例。@fedes。是的,谢谢你添加它。我试图让ALW保持简单,但可能过于简单化了,只关注显示的代码。@fedes。我决定根据你的评论进行编辑。只是吹毛求疵。Afaik,按照惯例,大写字母通常用于全局,其中类名是最扩展的用例。转录本iirc是一个全局实例,Smalltalk通常是SystemDictionary的唯一实例,还有一些其他实例。@fedes。是的,谢谢你添加它。我试图让ALW保持简单,但可能过于简单化了,只关注显示的代码。@fedes。我决定根据你的评论进行编辑。
content at: deckRank put: (Card newWithSuit: suitNumber rank: rankNumber).