2

我有兴趣创建自己的 Stream 子类,我想知道我应该重写哪些方法(在 pharo 和 Gemstone 上部署)。我有一个集合,里面有各种类型的东西,我希望能够流过它的一个子集,包含一个类的元素。我不想复制集合或使用 collect: 块,因为集合可能很大。我的第一个用例是这样的:

stream := self mailBox streamOf: QTurnMessage.
stream size > 1
    ifTrue: [ ^ stream at: 2 ]
    ifFalse: [ ^ nil ]

关于覆盖哪些方法的任何指针?

4

2 回答 2

5

在 Smalltalk 中,当我们说Stream我们指的是响应由一些方法给出的基本协议的对象时,例如 #next、#nextPut:、#contents 等。所以,在深入细节之前,我会说stream at: 2,正如你所说在您的示例中,这不是一个非常合适的表达方式。更合适的 a 表达式Stream

stream position: 2.
^stream next

因此,您首先要考虑的是您是在寻找 aStream还是Collection. 这个基本决定取决于您的对象必须实现的行为。

Stream如果您决定要使用#next 枚举元素,请使用的子类,即主要按顺序。但是,如果您想通过 访问您的元素at: index,请使用 的子类对您的对象建模SequenceableCollection.

如果您选择流,您将必须决定是仅访问它们以进行读取操作还是还想修改它们的内容。您对问题的描述似乎表明您只会阅读它们。因此,您必须首先实现的基本协议是

#next "retrieve the object at the following position and advance the position"
#atEnd "answer with true if there are no more objects left"
#position "answer the current position of the implicit index"
#position: "change the implicit index to a new value"

此外,如果您的流是只读的,请将您的类设为ReadStream.

如果您想继承更高级的方法,则必须实现一些其他附加消息。一个例子是#next:检索几个连续元素的子集合(它的大小由参数给出。)

如果您认为将对象建模为集合会更好,那么您必须实现的基本协议由以下三种方法组成

#at: index "retrieve the element at the given index"
#size "retrieve the total number of elements"
#do: aBlock "evaluate aBlock for every element of the receiver"

(我不认为你的收藏必须支持at:put:.

最近我们遇到了您描述的相同问题,并决定将我们的对象建模为集合(而不是流)。但是,无论您最终将采用哪种方法,我认为您应该尝试两种方法,看看哪一种更好。没有人会比您的 Smalltalk 系统给您更好的建议。

顺便说一句,还请注意,如果您有一个 (sequenceable) Collection,您将Stream免费获得一个:只需发送#readStream到您的收藏!

于 2015-03-28T19:26:04.740 回答
2

我需要覆盖nextatEnd. 我的Stream子类接受一个块和一个集合,并遍历集合中所有block计算结果为 true 的元素。

示例用法:

e := Array with: 1 with: 2 with: 3. 
a := QStream collection: e block: [ :i| i odd ].

a next. "1"
a next. "3"

这是它的核心:

Stream subclass: #QStream
    instanceVariableNames: 'collection block index found'
    classVariableNames: ''
    poolDictionaries: ''
    category: 'QDialog-Core'

initialize
    super initialize.
    index := 1.
    self search.

next
    | result |
    result := found.
    self search.
    ^result.

search
    [ index < collection size and: [ (block value: (collection at: index)) not ] ]
      whileTrue: [ index := index + 1 ].
    self atEnd
        ifTrue: [ ^ found := nil ]
        ifFalse: [ 
            found := collection at: index.
            index := index + 1 ]

atEnd
^   index > collection size
于 2015-03-28T20:42:03.760 回答