【问题标题】:Are literal strings mutable in smalltalk?Smalltalk中的文字字符串是可变的吗?
【发布时间】:2012-07-19 10:12:11
【问题描述】:

1)stringstring literal有什么区别

2) 一本书说'zero' at: 1 put: $h 会失败,因为文字是不可变的,但如果我这样做,'zero' copy at: 1 put: $h 会起作用,因为复制文字字符串会产生另一个不是文字的字符串。糊涂了!

【问题讨论】:

    标签: smalltalk squeak


    【解决方案1】:

    假设你有一个方法回答一个文字字符串(字面意思是其内容按字面意思写在源代码中)

    MyClass>>constantString
        ^'foo'
    

    现在,如果这个文字字符串是可变的,你可以讨厌地执行这个 sn-p

    MyClass new constantString at: 1 put: $b.
    

    然后,MyClass 的每个实例都会对#constantString 回答“boo”。但是,您无法理解为什么,因为源代码仍然指示“foo”。恶心……

    一些 Smalltalk 方言使这些文字字符串不可变,以避免这种意外的坏惊喜。有些没有虚拟机对不变性的支持,将全部责任交给用户。

    【讨论】:

    • 为什么需要 VM 支持?为什么不只拥有一个不实现 #at:put 的 StringLiteral 类?
    • 同意,也同意 #basicAt:put:,如果 VM 缺少镜像 object:basicAt:put: 和 withArgs:executeMethod: ,则保证不变性。就我个人而言,我希望所有 String 一旦构造后都是不可变的,即紧接在像 collect:、select: 或 WriteStream 内容这样的消息之后......如果你想要一个有状态的对象,你应该这样说。
    【解决方案2】:
    | a b |
    a := b := 'foo'.
    a == b. "=> true, so the identical string"
    a at: 1 put: $b.
    b "=> 'boo'
    

    所以在 Squeak 中,可能在 Pharo 中,字符串文字不是不可变的。

    其他 Smalltalks 确实支持不可变性,因此可能 那些 Smalltalks 中的字符串文字确实是不可变的。

    关于复制,也许您从其他语言中继承了假设。 'foo' 是一个字面量,因为存在用于创建 String 的语法,但实际上,'foo' 只是另一个对象。在 Squeak 和 Pharo 中,这些文字只是普通的 String 实例,因此您可以随意改变它们。

    正如上面的 sn-p 所示,这可能会导致意想不到的结果,因为如果将第一行更改为 a := 'foo'. b := 'foo'.,您最终仍会得到相同的结果:Squeak 悄悄地分享该文字,而不是创建一个新的具有相同的值。

    【讨论】:

    • 那么复制是如何改变不变性的呢?
    【解决方案3】:

    这本书是错的。在吱吱声中,字符串不是不可变的。那是哪本书?

    'zero' at: 1 put: $h; yourself. => '英雄'

    'zero' copy at: 1 put: $h; yourself => '英雄'

    字符是不可变的。如果他们不这样做会很有趣。

    【讨论】:

    • 其实书是一般的 SmallTalk 书,不是 Squeak 特有的。我想知道字符串和字符串字面量有何不同
    • 嗯,squeak 字符也是可变的。 'value' 实例变量仅在赋值 setValue: 中受到保护,但不会抵抗 instVarAt: 1 put: newValue。 setValue: newValue value ifNotNil:[^self error:'Characters are immutable']。价值 := 新价值。
    猜你喜欢
    • 2011-08-06
    • 1970-01-01
    • 2013-04-14
    • 2011-03-24
    • 1970-01-01
    • 1970-01-01
    • 1970-01-01
    • 1970-01-01
    相关资源
    最近更新 更多