Math 为什么法罗对算术的定义是+;和-基本上是重复的代码?

Math 为什么法罗对算术的定义是+;和-基本上是重复的代码?,math,smalltalk,pharo,Math,Smalltalk,Pharo,我浏览了Pharo的内部结构,发现算术+和-的定义非常相似: + aNumber "Refer to the comment in Number + " aNumber isInteger ifTrue: [self negative == aNumber negative ifTrue: [^ (self digitAdd: aNumber) normalize] ifFalse: [^ self digitSubtract: aNumber]]. aN

我浏览了Pharo的内部结构,发现算术+和-的定义非常相似:

+ aNumber
"Refer to the comment in Number + "
aNumber isInteger ifTrue:
    [self negative == aNumber negative
        ifTrue: [^ (self digitAdd: aNumber) normalize]
        ifFalse: [^ self digitSubtract: aNumber]].
aNumber isFraction ifTrue:
    [^Fraction numerator: self * aNumber denominator + aNumber numerator denominator: aNumber denominator].
^ aNumber adaptToInteger: self andSend: #+


在我看来,这完全违背了面向对象的设计方式,通常是不好的。为什么没有人找到更好的解决方案?

我能想到的最简单的事情是:

- aNumber
    ^self + aNumber negated
但是,这将产生成本:

  • 创建另一个中间大整数或分数
  • 再发送两条消息以执行-操作
我们在这里看到的是对优化的赞扬。不是过早的优化,这是一种广泛使用的低级操作

本规范中还有其他不完美的地方:

  • isInteger和isFraction的使用也可以被某种双重分派所取代
  • digitAdd:和digitSubtract:方法适用于存储为符号-幅值而不是2-补码的整数,这是一个不完全明显的实现细节,值得一提,或者最好将其重命名为digitaddmagnity:digitsubtractmagnity:

    • 这并不反对面向对象-行为是封装的,将复杂的行为隐藏在一个简单的API后面。(或者我们在Smalltalk中称之为消息协议)

      有很多代码重复。可以在其中放置一层间接寻址,并将代码保存在一个公共位置—但这是一个以牺牲紧凑性换取速度的示例—以内存占用换取速度。它还以牺牲速度为代价,我相信这是你们最关心的问题

      在我使用的第一个Smalltalk(基于ParcPlace实现,iirc)中,
      -
      函数简单地对参数求反,然后调用
      +
      函数。这使得
      -
      操作比
      +
      操作慢

      在软件开发中有很多潜在的权衡和优化——主要的权衡和优化是内存占用的速度(反之亦然)、开发速度的执行速度(反之亦然),以及现在让某些东西工作起来容易与长期让它工作和调整起来容易相比

      OO开发通常围绕优化开发速度而进行优化,以牺牲执行速度为代价,使用开发速度更快但运行速度较慢的高级语言;优化长期可维护性而不是即时性;并且使用大量内存来尽可能地从自然较慢的代码中挤出性能

      然而,这些只是概括。我敢肯定,所有这些都有反例

      - aNumber
          ^self + aNumber negated