【问题标题】:Can I extend built-in String class with my methods我可以用我的方法扩展内置的 String 类吗
【发布时间】:2019-05-14 11:29:42
【问题描述】:

我发现没有内置的trim (strip) 方法可以从内置String 类中的字符串中删除前导和尾随空格。我想用我的功能扩展它。是否可以?使用示例here,我尝试了以下代码:

String extend [
    trimleading: str [ |ch ret flag|
        ret := str.                 "make a copy of sent string"
        flag := true.
        [flag] whileTrue: [         "while first char is space"
            ch := ret first: 1.     "again test first char"
            ch = ' '                "check if space remaining" 
            ifTrue: [ ret := (ret copyFrom: 2 to: ret size)]    "copy from 2nd char"
            ifFalse: [flag := false] 
            ].
        ^ret                        "return modified string"
        ]
    trim: str [ |ret|
        ret := str. 
        ret := (self trimleading: ret).           "trim leading spaces"
        ret := (self trimleading: (ret reverse)). "reverse string and repeat trim leading"
        ^(ret reverse)                            "return re-reversed string"
        ]
].

oristr := '        this is a test  '
('>>',oristr,'<<') displayNl.
('>>',(oristr trim),'<<') displayNl.

上面的代码不起作用并给出以下错误:

$ gst string_extend_trim.st 

>>        this is a test  <<
Object: '        this is a test  ' error: did not understand #trim
MessageNotUnderstood(Exception)>>signal (ExcHandling.st:254)
String(Object)>>doesNotUnderstand: #trim (SysExcept.st:1448)
UndefinedObject>>executeStatements (string_extend_trim.st:23)

问题出在哪里,如何解决?谢谢。

编辑:以下代码有效,但不会更改原始字符串:

String extend [
    trimleading [ |ch ret flag|
        ret := self.                    "make a copy of sent string"
        flag := true.
        [flag] whileTrue: [             "while first char is space"
            ch := ret first: 1.         "again test first char"
            ch = ' '                    "check if space remaining" 
            ifTrue: [ ret := (ret copyFrom: 2 to: ret size)]    "copy from 2nd char"
            ifFalse: [flag := false] 
            ].
        ^ret                                "return modified string"
        ]
    trim [ |ret|
        ret := self.    
        ret := (self trimleading).  "trim leading spaces"
        ret := ((ret reverse) trimleading ). "reverse string and repeat trim leading"
        ^(ret reverse)                      "return re-reverse string"
        ]
].

oristr := '        this is a test  '
('>>',oristr,'<<') displayNl.
('>>',(oristr trim),'<<') displayNl.
('>>',oristr,'<<') displayNl.
oristr := (oristr trim).
('>>',oristr,'<<') displayNl.

oristr trim如何改变oristr?我不想写oristr := oristr trim。

【问题讨论】:

  • 您的第一个作业不会复制与注释相反的字符串。顾名思义,copyFrom:to: 确实如此。因此,实际上您复制的副本数量与前导(以及随后的尾随)空格一样多。

标签: string oop smalltalk gnu-smalltalk


【解决方案1】:

您已经解决的第一个问题:最初您定义了一个带有一个参数的方法trim:,但发送了一个不带参数的trim。

第二个问题是原地修改String。您可以使用self at: index put: aCharacter 和其他一些方法来更改字符以复制和覆盖范围,但您将无法更改字符串的大小(长度)。在我所知道的 Smalltalks 中,对象在创建后无法更改其大小。因此我建议您坚持在trim 中创建一个字符更少的新字符串。

在系统的任何地方都有一种方法可以将一个对象交换为另一个对象。它被称为become:。但我认为你不应该在这里使用它。根据 Smalltalk 的实现,您最终可能会产生不希望的副作用,例如在方法中替换字符串文字(因此下一个方法调用实际上会使用不同的、修剪过的字符串来代替文字)。

【讨论】:

    【解决方案2】:

    您的代码与您链接的示例之间的区别在于,在示例中它们扩展了自定义类,但您扩展了核心类。不同之处在于您应该加载代码并运行它的方式。您应该在 GNU-Smalltalk 中使用 Packages 来构建它。 @lurker how to use extened classes in gst 对 SO 有一个很好的回答,如果你喜欢,请阅读并点赞,我不想在这里复制信息。

    使您的代码适应String extend:

    String extend [
        trimleading: str [ |ch ret flag|
            ret := str.                     "make a copy of sent string"
            flag := true.
            [flag] whileTrue: [         "while first char is space"
                ch := ret first: 1.         "again test first char"
                ch = ' '
                ifTrue: [ ret := (ret copyFrom: 2 to: ret size) ]    "copy from 2nd char"
                ifFalse:  [flag := false ] 
            ].
            ^ ret                                "value is modified string"
        ]
        trim [ | ret |
            ret := self trimleading: self.           "trim leading spaces"
            ret := self trimleading: (ret copy reverse). "reverse string and repeat trim leading"
            ^ (ret reverse)                      "return re-reverse string"
        ]
    ].
    
    oristr := '        this is a test  '.
    ('>>',oristr,'<<') displayNl.
    ('>>',(oristr trim),'<<') displayNl.
    ('>>',oristr,'<<') displayNl.
    oristr := (oristr trim).
    ('>>',oristr,'<<') displayNl.
    

    您将消息#trim 发送到origstr 变量,因此您必须在没有任何参数的情况下进行定义。但是,这不适用于#trimleading:,所以我把你以前的代码放在那里。

    注意:您应该真正了解self 关键字以及它的作用并理解它 - 您错误地使用了它。您分配了 ret := self 值,但您不使用它,您只是用下一个分配覆盖它。

    【讨论】:

      猜你喜欢
      • 2011-11-21
      • 2021-12-25
      • 1970-01-01
      • 1970-01-01
      • 1970-01-01
      • 1970-01-01
      • 1970-01-01
      • 1970-01-01
      • 1970-01-01
      相关资源
      最近更新 更多