簡體   English   中英

Smalltalk如何創建不可變的實例變量?

[英]Smalltalk How to create immutable instance variable?

我有一個帶有實例變量var的類。
我不希望將變量修改/分配給值,除非使用Class方法創建對象時。

isImmutable:aBoolean是將可變對象轉換為不可變對象的方法,反之亦然。
有人可以提供正確的語法給我嗎?

我還沒有嘗試過,但是我很確定isImmutable不會成功。 假設確實確實使對象不可變,那么它將使instVar 指向的對象不可變,而不是instvar本身不可變。

最好的選擇是根本不為變量包含特定的Mutator,而是在初始化時進行如下設置:

MyClass class>>newWithFoo: aFoo
   ^self basicNew initializeWithFoo: aFoo; yourself

MyClass>>initializeWithFoo: aFoo
   self initialize.
   foo := aFoo.

這樣,類外部的任何人都可以影響變量的唯一方法是通過調用MyClass newWithFoo:創建一個新實例MyClass newWithFoo:

(不使用#instVarNamed:put:類的反射方法進行計數-您幾乎無能為力,但是使用它們的任何人都知道他們仍然違反了類的約定)。

為什么要使對象不可變? 以一種顯而易見的方式聲明您的API是否足以使用該類而不替換實例變量?

我使用代碼實現了它:

MyClass class>>classMethod: aValue

anObject := self new value:aValue.
anObject isImmutable: true.
^anObject.

要記住的一件事是,不變性在對象圖中的單個級別上起作用。 實例變量有點像C ++中的常量指針,地址不能更改,但是內容可以更改。
這是一個小例子:

| a b |
a := Array with: 1.
b := Array with: a.
b beImmutable.
b at: 1 put: nil.
^b

將以NoModificationError結尾,由於b是不可變的,因此您無法編寫b的任何實例/索引變量。
但是您可以寫入b的實例/索引變量所指向的對象:

| a b |
a := Array with: 1.
b := Array with: a.
b beImmutable.
a at: 1 put: 2.
^b

將會成功,並且b現在是#(#(2))而不是#(#(1))

如果您要這樣做,也可以安排將不可變性進一步傳播到對象圖的下方(但要注意循環)。

暫無
暫無

聲明:本站的技術帖子網頁,遵循CC BY-SA 4.0協議,如果您需要轉載,請注明本站網址或者原文地址。任何問題請咨詢:yoyou2525@163.com.

 
粵ICP備18138465號  © 2020-2024 STACKOOM.COM