pharo - 现有的库类应该如何扩展?

标签 pharo

normalize: sum
    | strategy normalizingSum |
    strategy := sum collect: [ :each | each max: 0.0 ].
    normalizingSum := strategy sum.
    ^strategy collect: [ :each |
        normalizingSum strictlyPositive
        ifTrue: [ each / normalizingSum ]
        ifFalse: [ 1.0 / Action subclasses size ]
        ]

我想让上面的方法成为一个实例方法,而不必显式地将 sum 传递给它。问题不是我做不到方法或者我不能把它放进Array类(class)。只是来自函数式语言,我发现自己完全偏离了这里对我的期望。

据我所知,作为惯例,大多数 Pharo 方法直接在实例上工作,而在函数式语言中,人们要做的是定义一个类似于 C#/Java 中的静态方法的函数。

一种选择是将方法放入 Pharo 中的元类中,但 Pharo 的语法不太适合这种编程风格。例如,它没有解释在我观察到的所有库代码中对实例方法的严重倾斜的管道运算符。

通过直接将方法放入标准库类来扩展标准库类对我来说感觉有点不对。当需要将更改推送到 Github 时,事情究竟会如何发展?直接放入Array class 感觉它最终会变成版本控制的噩梦。

另一种选择是从 Array 继承.这对于我现在正在做的问题可能没问题,但后来我想做一个不同的问题并且不想共享实现。

我应该把它放在一个特征中并将特征添加到 Array ?

最佳答案

这里的问题来自这样一个事实,即我们只考虑您的收藏应该回答的一条消息:#normalized .在您的代码中,集合 sum是需要归一化的对象。因此,很容易说 sum normalized .但是,我不建议添加 #normalizedArray (或 Collection )因为您的特定规范化的逻辑不是 Array 固有的: 这取决于 Action ,这看起来是一个在您的项目上下文中有意义的概念。

这并不意味着你永远不应该扩展 Array带着你的东西。这只意味着,如果您的扩展不是内在的,那么这样的决定需要更多的思考。

在这种情况下,我建议分析是否像 sum 这样的集合。在您的项目中有任何其他固有的行为。在这种情况下,我会考虑使用一个类来表示它们并添加到此类消息中,例如 #normalized ,加上与这些对象相关的任何其他内容。

举个例子,假设你的类名为 StrategyCollection .你可以在里面定义

strategy
  ^sum collect: [:each | each max: 0.0].

哪里sum现在是您类(class)的 ivar。然后你可以定义
normalized
  strategy := self strategy.
  normalizingSum := strategy sum.
  ^strategy collect: [:each |
    normalizingSum strictlyPositive
      ifTrue: [each / normalizingSum]
      ifFalse: [1.0 / Action subclasses size]]

顺便说一下,它可以重写为
normalized
  | strategy normalizingSum |
  strategy := self strategy.
  normalizingSum := strategy sum.
  ^normalizingSum strictlyPositive
     ifTrue: [strategy collect: [:each | each / normalizingSum]]
     ifFalse: [strategy class new: sumstrategy size withAll: 1.0 / Action subclasses size]

如果您除了 #max: 0 之外还有其他策略,您可以轻松地调整上面的代码,以便使用 perform: 使其更通用。或者有一个特殊的子类 StrategyCollection它实现了自己的 #strategy 版本.

我还建议为表达式 Action subclasses size 添加一个方法.一些关于
actionCount
  ^Action subclasses size

然后在 #normalized 中使用它.表达式 Action subclasses size很脆弱,很可能会出现在其他方法中。例如,如果明天您决定将 Action 的一些子类分组在另一个抽象子类下,Action的子类数不会适应这样的重构。更一般地说,您的对象的行为不应该取决于您组织代码的方式,因为这属于抽象的元级别。

关于pharo - 现有的库类应该如何扩展?,我们在Stack Overflow上找到一个类似的问题: https://stackoverflow.com/questions/54966247/

相关文章:

stream - 将代码移植到Pharo 2.0

smalltalk - 在编译器类中查找compile&evaluate方法等的Pharo文档

smalltalk - 如何从 Pharo 中的调试器中复制堆栈跟踪?

string - 在 Smalltalk 中,如何从数组中选择字符串和整数

loops - 嵌套循环 Smalltalk

smalltalk - 是否有一个脚本可以将 Pharo 核心图像变成更有用的东西,包括 OmniBrowser?

syntax-highlighting - 将 Pharo 的语法突出显示带到网络上

smalltalk - Pharo/Smalltalk中 ">>"的使用

smalltalk - 字典到字符串

string-comparison - 如何比较 Smalltalk 中的本地化字符串?