2014-09-29 11 views
5

Tôi mới bắt đầu và bắt đầu khám phá các khả năng lập trình meta của nó. Tôi đã bị mắc kẹt với việc thêm các thuộc tính còn thiếu trên một cuộc gọi hàm tạo bean.Thêm thuộc tính bị thiếu trong lời gọi hàm tạo @Canonical bean groovy?

Trong một lớp được sử dụng với FactoryBuilderSupport, tôi muốn tự động thêm các thuộc tính chưa được xác định và cung cấp trong suốt cuộc gọi hàm tạo. Đây là tước xuống phiên bản:

@Canonical 
class MyClass { 
    def startDate 
    def additionalProperties = [:] 

    def void propertyMissing(String name, value) { 
     additionalProperties[name] = value 
    } 
} 

Tuy nhiên, nếu tôi xây dựng các lớp học với đặc tính không rõ, các proprty không được thêm vào nhưng tôi nhận được một MissingPropertyException thay vì:

def thing = new MyClass(startDate: DateTime.now(), duration: 1234) 

Thời hạn sở hữu không tồn tại và tôi dự kiến ​​nó sẽ được xử lý qua propertyMissing. Theo như tôi hiểu groovy, gọi hàm tuple-constructor kết quả trong một cuộc gọi hàm tạo không có đối số, theo sau là các cuộc gọi đến các bộ định tuyến được tạo ra bằng groovy. Vậy tại sao tôi nhận được MissingPropertyException?

Vì tôi mới bắt đầu, tôi có thể thiếu một số quy tắc AST hoặc MOP cơ bản. Tôi đánh giá cao sự giúp đỡ của bạn.

+0

như một cách giải quyết, bạn có thể sử dụng 'Expando', mà ctor xử lý này: '@groovy.transform.InheritConstructors @ groovy.transform.ToString @ groovy.transform.EqualsAndHashCode lớp MyClass kéo dài expando {def startDate} ' – cfrick

Trả lời

1

Nếu bạn sử dụng @Canonical và bạn xác định đối tượng lớp đầu tiên với def như bạn đang làm với startDate chú thích tạo ra các nhà thầu sau:

@Canonical 
class MyClass { 
    def startDate 
    def additionalProperties = [:] 

    def void propertyMissing(String name, value) { 
      additionalProperties[name] = value 
    } 
} 

// use reflection to see the constructors 
MyClass.class.getConstructors() 

constructors tạo:

public MyClass() 
public MyClass(java.lang.Object) 
public MyClass(java.util.LinkedHashMap) 
public MyClass(java.lang.Object,java.lang.Object) 

Trong @Canonicaldocumentation bạn có thể thấy giới hạn theo sau:

bình thường bản đồ kiểu quy ước đặt tên

Groovy sẽ không có sẵn nếu tài sản đầu tiên có kiểu LinkedHashMap hoặc nếu có một bản đồ duy nhất, bất động sản AbstractMap hoặc HashMap

Do public MyClass(java.util.LinkedHashMap) được tạo ra bạn không thể sử dụng tuple-constructor và bạn nhận được MissingPropertyException.

Đáng ngạc nhiên nếu bạn xác định first đối tượng của bạn (lưu ý rằng tôi nói first) với một type thay vì sử dụng def, @Canonical chú thích không thêm public MyClass(java.util.LinkedHashMap) và sau đó tuple-constructor công trình gọi bạn, hãy xem đoạn mã sau:

@Canonical 
class MyClass { 
    java.util.Date startDate 
    def additionalProperties = [:] 

    def void propertyMissing(String name, value) { 
      additionalProperties[name] = value 
    } 
} 
// get the constructors 
MyClass.class.getConstructors() 
// now your code works 
def thing = new MyClass(startDate: new java.util.Date(), duration: 1234) 

Bây giờ các nhà thầu tạo ra là:

public MyClass() 
public MyClass(java.util.Date) 
public MyClass(java.util.Date,java.lang.Object) 

vì vậy, kể từ khi có không phải là public MyClass(java.util.LinkedHashMap) giới hạn không áp dụng và bạn hoạt động cuộc gọi tuple-constructor. Ngoài ra tôi muốn nói rằng kể từ khi giải pháp này hoạt động tôi không thể tranh luận tại sao ... Tôi đọc tài liệu @Canonical một lần nữa và một lần nữa và tôi không thấy một phần mà hành vi này được mô tả, vì vậy tôi không ' t biết tại sao hoạt động theo cách này, tôi cũng thực hiện một số cố gắng và tôi là một chút khó hiểu, chỉ khi các yếu tố firstdef các public MyClass(java.util.LinkedHashMap) được tạo ra i.e:

@Canonical 
class MyClass { 
    def a 
    int c 
} 
// get the constructors 
MyClass.class.getConstructors() 

đối tượng đầu tiên được xác định như def ...

public MyClass() 
public MyClass(java.lang.Object) 
public MyClass(java.util.LinkedHashMap) // first def... 
public MyClass(java.lang.Object,int) 

Bây giờ nếu tôi thay đổi thứ tự:

@Canonical 
class MyClass { 
    int c 
    def a 
} 
// get the constructors 
MyClass.class.getConstructors() 

Bây giờ đầu tiên không phải là defpublic MyClass(java.util.LinkedHashMap) không được tạo ra:

public MyClass() 
public MyClass(int) 
public MyClass(int,java.lang.Object) 

Hope this helps,

Các vấn đề liên quan