繁体   English   中英

我可以使用我的方法扩展内置的String类

[英]Can I extend built-in String class with my methods

我发现没有内置的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

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

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

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

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

要使代码适应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值但不使用它,只需用下一个分配覆盖它。

暂无
暂无

声明:本站的技术帖子网页,遵循CC BY-SA 4.0协议,如果您需要转载,请注明本站网址或者原文地址。任何问题请咨询:yoyou2525@163.com.

 
粤ICP备18138465号  © 2020-2024 STACKOOM.COM