2014-01-05 44 views
5

我想在埃菲爾做一個不可變的POINT類。下面的代碼是否定義了一個? xy字段的{NONE}可訪問性足夠嗎?我可以寫一些類似於x = x'的類,或者我還能如何實現不變性?在埃菲爾不可變的類

class POINT 
    create 
     make 
    feature {NONE} 
     x: DOUBLE 
     y: DOUBLE 
    feature 
     make (x_: DOUBLE; y_: DOUBLE) 
     do 
      x := x_ 
      y := y_ 
     ensure 
      set: x = x_ and y = y_ 
     end 

    feature --accessors 
     get_x: DOUBLE 
     do 
      Result := x 
     ensure 
      Result = x 
     end 
    end 
+2

記根據埃菲爾風格指南訪問者是名詞,因此沒有獲得前綴。它會讓你的代碼更易於閱讀(幾乎所有語言都是如此)。但是當你使屬性自己的訪問者在下面看到答案時,它也不會有get前綴。 –

回答

5

埃菲爾不允許改變其客戶端的屬性。例如,下列代碼被拒絕:

p: POINT 
... 
p.x := 5.0 

因此,不需要提供getter(就像其他語言一樣)。只要x已足夠導出到客戶端類別,您就可以使用p.x。所以,你的例子的代碼可以簡化爲

class POINT 
create 
    make 
feature -- Access 
    x: DOUBLE 
    y: DOUBLE 
feature {NONE} -- Creation 
    make (x0: DOUBLE; y0: DOUBLE) 
     -- Initialize object with `x0' and `y0'. 
    do 
     x := x0 
     y := y0 
    ensure 
     set: x = x0 and y = y0 
    end 
end 

注意,創建過程是了出口,否則將有可能使用它作爲一個正常的(即非創作)例程和更改屬性,這是我們能夠做一些事情如下

create p.make (1, 1) 
p.make (2, 3) 
print (p) 

,這將打印(2, 3),即你將能夠改變原始對象p的價值,使其可變。

雖然現在不能直接更改屬性,但仍可以對POINT類型的對象調用功能copy並更改整個對象。如果你想避免這種情況爲好,該功能可以在類POINT被重新定義爲引發異常,甚至有一個後置條件False導致運行時引發異常你:

copy (other: like Current) 
     -- <Precursor> 
    do 
     (create {EXCEPTIONS}).raise ("Attempt to change an immutable object.") 
    ensure then 
     is_allowed: False 
    end 
+1

請注意,如果您確實想使用「p.x:= 5.0」,則可以使用分配器。請參閱:http://docs.eiffel.com/book/examples/example-self-initializing-attributes-and-assigner-commands。 –

+0

我不明白,如果我將make設置爲private,會發生什麼情況? 現在如果我打電話:create p1.make(1,1);打印(P1); \t創建p1.make(2,3);打印(p1)比我得到一個結果:(1,1)(2,3)和相同的情況發生時,未設置可見性 –

+0

,如果我從這個類繼承,我仍然可以重新定義make功能,但{NONE}聲明即使是子類也不能更改該功能。或者創建方法有一些不同的規則呢? –