2011-07-04 6 views
5

Sử dụng Groovy 1.8. Tôi đang cố gắng để tạo ra một định nghĩa lớp năng động sẽ cache thuộc tính cho mỗi đối tượng. Tôi đã sử dụng propertyMissing mà không thêm thuộc tính vào đối tượng tốt. Tôi chỉ nghĩ rằng bộ nhớ đệm các thuộc tính sẽ hiệu quả hơn. Đúng?Thuộc tính động Groovy trên mỗi đối tượng

Lưu ý rằng mỗi cá thể phải có các thuộc tính khác nhau của riêng nó.

Đoạn code dưới đây hoạt động tốt:

class C {} 
def c = new C() 
c.metaClass.prop = "a C property" 
println c.prop 

def x = new C() 
x.prop 

chí đầu ra:

a C property 
groovy.lang.MissingPropertyException: No such property: prop for class: C 

Nếu tôi cần phải này còn gì phải bàn:

class A { 
    def propertyMissing(String name) { 
     if(!this.hasProperty(name)) { 
      println "create new propery $name" 
      this.metaClass."$name" = "Dyna prop $name" 
      println "created new propery $name" 
     } 
     this.metaClass."$name" 
    } 
} 

a = new A() 
println a.p1 

Đối A, tôi nhận được như xa như " tạo thuộc tính mới ", nhưng dòng this.metaClass."$name" = "Dyna prop $name" không thành công với: No such property: p1 for class at line 5

Có gì không ổn?

Trả lời

8

Mã này nên làm những gì bạn muốn:

class A { 
    A() { 
    def mc = new ExpandoMetaClass(A, false, true) 
    mc.initialize() 
    this.metaClass = mc 
    } 

    def propertyMissing(String name) { 
    println "create new propery $name" 
    def result = "Dyna prop $name" 
    this.metaClass."$name" = result 
    println "created new propery $name" 
    result 
    } 
} 

a = new A() 
println a.p1 
println a.p1 

Đó kết quả đầu ra:

create new propery p1 
created new propery p1 
Dyna prop p1 
Dyna prop p1 
1

ExpandoMetaClass không thực sự được thiết kế để sử dụng sau khi khởi tạo hoặc biến mẫu (xem tham chiếu bên dưới ít nhất là từ 1,6 trở lên).

Có thể bạn muốn sử dụng Runtime mixins. Thông tin thêm herehere.

Bạn có thể muốn đọc blogpost, cách giải quyết được cung cấp để xác định thuộc tính khi chạy. Và liên quan groovy bug (đó không thực sự là một lỗi) liên quan đến nó.

tôi thấy trong phần ý kiến ​​và xác nhận ít nhất là trong phiên bản tài liệu 1.6 ExpandoMetaClass:

Bằng phương pháp mặc định chỉ được phép được bổ sung trước khi khởi tạo() là gọi. Nói cách khác, bạn tạo ExpandoMetaClass mới, thêm một số phương thức và sau đó gọi khởi tạo(). Nếu bạn tìm cách thêm phương thức mới sau khởi tạo() đã được gọi là lỗi sẽ bị ném.

+0

Aha .. Bạn chỉ có thể làm điều đó vào thời gian biên dịch .. quá tệ. – Ayman

+0

Bạn có thể sử dụng Runtime mixin cho thời gian chạy – Manny

+0

Sửa liên kết bị hỏng "blogpost": http: // blog.enfranchisedmind.com/2008/06/groovy-metaclass-bug/ –

6

Tại sao bạn không lưu trữ thuộc tính năng động của bạn trong một HashMap đơn giản?

class Foo { 
    def storage = [:] 
    def propertyMissing(String name, value) { storage[name] = value } 
    def propertyMissing(String name) { storage[name] } 
} 
def f = new Foo() 
f.foo = "bar" 

Đây là ví dụ tiêu chuẩn từ: http://groovy.codehaus.org/Using+methodMissing+and+propertyMissing

Lưu ý, bạn không cần phải kiểm tra xem tài sản thực sự là mất tích ... nếu nó sẽ không bị mất, phương pháp này sẽ không được được gọi ngay từ đầu.