2015-07-12 35 views
4

下面的代碼打印出「假」:的Smalltalk /佳樂串淺平等

a := 'aaa'. 
b := a deepCopy. 
Transcript show: (a == b). 

我確實希望這種行爲,我解釋到,這將是deepcopy的返回一個新的對象「B」這是一個完全不同的因爲運算符「==」通過引用比較的結果是「false」,所以比「a」更快。那是對的嗎?

不過,我不明白爲什麼下面的代碼會產生「真」:

a := 'aaa'. 
b := 'aaa'. 
Transcript show: (a == b). 

在這裏,我們做了兩個分配到兩個不同的對象,「A」和「B」,並且不應該有它們之間的任何關係除了它們包含相同的值。但是如果運算符「==」通過引用而不是按值進行比較,爲什麼比較的結果是「真」?

+0

在第一種情況下,不同的對象實例,所以'false'。在第二種情況下,編譯器/解釋器顯然認爲使'a'和'b'引用相同的字符串對象是有效的,因爲這些值是相同的,並且它節省了內存,所以'true'。 – lurker

回答

4

在這兩種情況下,同樣的誤解是問題不是「會發生什麼?」,而是「保證什麼?」。關鍵是不能保證'aaa' == 'aaa',但編譯器和虛擬機可以自由地做這件事。對於複製的情況也是如此。由於字符串是不可變的,我想沒有什麼可以說複製一個字符串不能返回相同的對象!

在第一個例子中,像往常一樣,最好的老師是圖像。 #deepCopy代表#shallowCopy,它在某些時候評估class basicNew: index,並將字符複製到新對象中。所以,這個特定的實現將總是創建一個新的對象。

+0

很好的答案。通常,虛擬機級別上沒有太多事情發生:虛擬機只是執行我們告訴它的內容,並創建我們也告訴的對象。編譯器中的圖像端發生了一些事情。它有點隱藏,但在Encoder的listSet實例變量中...它包含一個使用#literalEqual的PluggableDictionary:用於測試關鍵相等。所以如果兩個文字被認爲是平等的,那麼它們不會被重複。事實上,編譯器假定文字不會發生變異,儘管它們在技術上是可變的。 –

+0

好點,@ aka.nice。我會添加提到編譯器的答案... –

2

除了什麼肖恩DeNigris說,爲什麼比較true在第二種情況的原因是,當你執行所有三個語句一起,編譯器要聰明,只一次'aaa'並創建對象分享他們的ab

,如果你把這個變成一個方法*同樣的情況:

Object subclass: #MyClassA 
    instanceVariableNames: '' 
    classVariableNames: '' 
    poolDictionaries: '' 
    category: 'MyApp' 


!MyClassA methodsFor: 'testing' stamp: nil prior: nil! 
testStrings 

    | a b | 
    a := 'aaa' 
    b := 'aaa' 
    ^a == b 
! ! 
MyClassA testStrings " ==> true" 

但這發生,如果他們是在不同的方法:

Object subclass: #MyClassB 
    instanceVariableNames: '' 
    classVariableNames: '' 
    poolDictionaries: '' 
    category: 'MyApp' 


!MyClassB methodsFor: 'testing' stamp: nil prior: nil! 
a 

    | a | 
    a := 'aaa' 
    ^a 
! ! 
!MyClassB methodsFor: 'testing' stamp: nil prior: nil! 
b 

    | b | 
    b := 'aaa' 
    ^b 
! ! 
!MyClassB methodsFor: 'testing' stamp: nil prior: nil! 
testStrings 

    ^self a == self b 
! ! 
MyClassB testStrings " ==> false" 

這是因爲在Squ EAK,像蜇傷文字對象存儲在它們在

*定義的方法的方法目標:從技術上講,每個DoItPrintIt,那就是當你只是通過按鍵執行代碼,被編譯到一個方法吱。

0

這是我從網上零散的免費Smalltalk的一本書知道,但我無法找到參考:

正如你所期望的一個類的實例是在內存中的唯一對象。 deepCopy首先有意創建一個對象,然後在其中存儲一個現有實例的副本。

但是,數字,字符和字符串被Smalltalk視爲原始數據類型。當文字數據(也被稱爲文字)被分配給變量時,它們首先針對用戶不可見的局部範圍字典進行檢查,並保存文字以檢查它們是否已被添加到它。如果他們沒有,他們將被添加到字典中,變量將指向字典字段。如果之前分配了相同的文字數據,則新變量只會指向包含相同文字的局部範圍字典字段。這意味着兩個或多個分配相同文字的變量指向相同的字典字段,因此是相同的對象。這就是爲什麼你的問題中的第二個比較返回true。