首页 > 解决方案 > 我可以用我的方法扩展内置的 String 类吗

问题描述

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

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

标签: stringoopsmalltalkgnu-smalltalk

解决方案


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

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

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


推荐阅读