如何在Smalltalk

时间:2016-11-20 02:52:19

标签: smalltalk multiplying

我几天前正在学习Smalltalk,我正在研究的项目基本上是从Shape类中实现Circle类的Area和Perimeter。换句话说,Shape是Circle的超级类。

当我运行我的代码时,我得到错误说,"数字原语期望数字参数,得到"。我相信错误的发生是因为我将整数与浮点值相乘。我不知道如何修复错误,所以如果有人可以请给我一些建议吗?

P.S - 我使用的是usmalltalk,它是Smalltalk的特定版本,但它具有相同的功能。

(class Shape Object 
   (Perimeter Area)
   (method getPerimeter() Perimeter)

   (method setPerimeter:(Perim)
       (set Perimeter Perim) 
   )


   (method CreateShape::(Perim Ar)
      (set Perimeter Perim)
      (set Area Ar)
      self
   )

   (class-method NewShape:: (Perimeter Area)
        (CreateShape:: (new self) Perimeter Area)
    )
)


(class Circle Shape
   (Radius)

   (method getRadius() Radius)

   (method setRadius:(radi)
       (set Radius radi)
       (set Perimeter (* (* 2 (asFloat (/ 22 7))) Radius)) #The error exits here
       (set Area (* (* (asFloat (/ 22 7)) Radius) Radius))
   )

   (method CreateCircle:(radi)
       (set Radius radi)
       self
   )

   (class-method NewCircle: (Radius)
       (CreateCircle: (new self) Radius)
   )

)

1 个答案:

答案 0 :(得分:4)

您正在使用的Smalltalk方言不遵循传统的Smalltalk语法,所以让我将有问题的表达式翻译成更熟悉的语法。

让我们解析表达式

(* (* 2 (asFloat (/ 22 7))) Radius)

在下文中,-->右侧的表达式是左侧表达式的传统形式。

第1步:

/ 22 27 --> 22/27

第2步:

asFloat(/ 22 7) --> (22/27) asFloat

第3步:

* 2 (asFloat (/ 22 27)) --> 2 * (22/27) asFloat

第4步:

* (* 2 (asFloat (/ 22 27)) Radius) --> (2 * (22 / 27) asFloat) * Radius

因此,此处的错误表示Radius不是数字。正如评论中所建议的那样,问题是Radius变量没有被分配一个正确的(即数字)值,而这正是错误消息以某种方式试图告诉的。

当然,Radius变量从发送到radi方法的setRadius:参数中获取其值。这意味着问题的根源在setRadius:的发件人中。但是这里对源代码的分析变得棘手,因为它是 static 并且它没有显示程序执行中的步骤序列。

理解问题的更好方法是动态。在Smalltalk中,您可以在调试器的帮助下完成此操作。我不熟悉您正在使用的Smalltalk方言,但是当弹出错误时,应该提供一些调试代码的方法。接受该选项并检查在发出错误信号之前发送的消息列表。找到在步骤4中评估表达式的方法后,检查Radius变量的值并查看其中的内容。它不应该是数字,否则不会有任何错误。从那里你应该能够追溯到正式参数radi获得其实际值的地方,这将导致问题的根源。

最后一句话。您的问题在Smalltalk中显示如何将整数与浮点数相乘。答案是使用* 将它们相乘。 Smalltalk将弄清楚如何继续。您不需要发送任何转换消息,例如asFloat等(您可以从代码中删除它们以简化它。)Smalltalk动态类型可以让程序员免于在类型转换变量中花费时间。不是因为编译器中有任何魔法,而是因为语言的多态性。