2016-03-14 40 views
4

在Groovy中有一個@運算符,它允許直接字段訪問。然而,它看起來不適用於在超類中聲明的字段。考慮兩個的Java(不Groovy的)類:Groovy中用於超類的字段訪問

class Entity { 
    private Long id; 

    Long getId() { 
    return id; 
    } 
} 

class User extends Entity { 
} 

然後調用在Groovy中直接訪問

User user = new User(); 
[email protected] = 1L 

與異常結束:groovy.lang.MissingFieldException: No such field: id for class User

當我嘗試使用標準訪問user.id = 1L我得到groovy.lang.ReadOnlyPropertyException: Cannot set readonly property: id for class User

是否有任何選項可以配置在超類中聲明ss字段?

+0

你可以不用'@'來訪問它,爲什麼你需要直接訪問? – Opal

+0

我沒有編號爲 –

+0

你有,因爲它是爲你生成的。 – JBaruch

回答

2

你可能需要申報財產的保護,而不是:

class Entity { 
    protected Long id; 

    Long getId() { 
    return id * 2; 
    } 
} 

class User extends Entity { 
} 

User user = new User(); 
[email protected] = 1L 

assert [email protected] == 1L 
assert user.id == 2L 

這是直接進入現場操作的修改示例。

+0

將域名標記爲受保護的作品 – Ceekay

2

不能從子類中訪問私有字段(它們不會被繼承)。 儘管Groovy允許您比Java反射更容易訪問私有字段,但它仍然無法訪問不存在的字段。

+0

正如我所提到的,這些類是Java而不是Groovy,所以這裏沒有setter –

+0

但是,私有字段不會被繼承。我會編輯我的答案,但主要信息是相同的:私有字段不會被繼承。 – JBaruch

+1

我一直在尋找一些可以直接說我對超類的領域感興趣的構造:像user @ @ super.id或類似的東西。然後,等同於user.getClass()。getSuperclass()。getDeclaredField() –

2

你可以通過普通的Java反射來訪問,但我不知道如何使這個更「Groovy」。

User user = new User() 
fields = user.getClass().superclass.declaredFields 
idField = fields[0] 
idField.accessible = true 
idField.set(user, 2L) 
println idField.get(user) 
+0

或者可口的;-) –

+0

是的,我很驚訝我沒有看到更多的「Groovy」解決方案。令人失望。我能做的最好的辦法就是刪除一些'set'和'get'前綴和一些parens。真?!!! –

0

讓我復活這個問題,因爲最近我正在經歷類似的事情。這裏有一些想法...

由於它需要測試,也許等於通過等值比較而不是直接檢查/設置字段?

值得考慮的模式是否替代是封裝。我的意思是,如果在理想情況下不需要觸摸prod代碼中的這些字段,他們也不需要在測試中被觸摸。

Entity將具有基於equalshashCode實施的自己的字段。 龍目島的@EqualsAndHashCode註釋可以幫助減少樣板。

測試然後像expect: new Entity(id) == new Entity(id)(假設有這樣的構造函數)。

如果平等是不走包範圍可能會提供更好的封裝用合適的封裝結構(主/ src目錄/ JAVA)的方式:

package foo.bar 

public class Entity { 
    Long id 
} 

控制在id訪問現在和獨立的更加靈活的測試代碼。雖然User extends Entity可以有如果放置在不同的包中的id沒有接入時,測試代碼可具有類訪問它,如例如(SRC /測試/常規):

package foo.bar 

class EntityAccess { 
    private final Entity entity 

    EntityAccess(Entity entity) { 
     this.entity = entity 
    } 

    static EntityAccess access(Entity entity) { 
     new EntityAccess(entity) 
    } 

    Long getId() { 
     entity.id 
    } 

    void setId(Long id) { 
     entity.id = id 
    } 
} 

我確信樣板可以減少一些花哨的Groovy AST註釋。問題的關鍵是督促代碼可以保持隱藏,而在測試領域,與EntityAccess.access靜態導入,現場無需任何Groovy的hax0rs訪問:

given: access(entity).id = 5設置或expect: access(entity).id == 5主張對實體的ID。

如果可能的話,我寧願保持EntityUser不變,並通過平等測試而不改變對象狀態。