2012-04-17 40 views
15

Có cách nào để làm cho groovy bỏ qua các thuộc tính phụ trong bản đồ trong quá trình khởi tạo đối tượng không? Ví dụ:Groovy - Bỏ qua các thuộc tính phụ trong bản đồ trong quá trình đối tượng đối tượng

class Banana{ 
    String name 
} 
def params = [name:'someGuy', age:13] 
new Banana(params) 

Trong ví dụ này, groovy ném một số tài sản đó: ngoại lệ tuổi (rõ ràng vì tuổi không được định nghĩa trong lớp Banana Nếu không phải dùng đến tay lập bản đồ chỉ các thuộc tính mong muốn từ bản đồ để các nhà xây dựng. của lớp Chuối, là có một cách để nói với chuối để bỏ qua các thuộc tính thêm?

tôi nhận thấy rằng Grails lớp miền không bị vấn đề này, và tôi muốn các hành vi tương tự ở đây!

Cám ơn sự giúp đỡ và lời khuyên của bạn!

Trả lời

10

Thật không may, không có cách nào được xây dựng để làm điều này trong groovy. Grails thực hiện nó bằng cách tạo ra các hàm tạo riêng cho các đối tượng miền. Một cách giải quyết đơn giản là sử dụng một constructor như thế này:

Banana(Map map) { 
    metaClass.setProperties(this, map.findAll { key, value -> this.hasProperty(key) }) 
} 
+1

Rõ ràng, bạn phải chắc chắn rằng bản đồ params của bạn không chứa các phím 'class' hoặc 'metaClass', hoặc Exceptions/weirdness sẽ xảy ;-) –

+0

Cảm ơn bạn - Tôi thích điều này tính năng của grails, tôi đã hy vọng nó không phải là thông qua các thủ thuật thông minh nhưng là một tính năng ngôn ngữ để thay thế. Oh well. Workaround của bạn nên làm các trick mặc dù, cảm ơn! – Quad64Bit

2

Một cách khác mà không ảnh hưởng đến hiệu suất nếu tất cả các thuộc tính có mặt:

public static Banana valueOf(Map<String, Object> params) { 
    try { 
     return new Banana(source) 
    } catch (MissingPropertyException e) { 
     log.info(e.getMessage()) 
     source.remove(e.property) 
     return valueOf(source) 
    } 
} 
11

Có một cách đơn giản hơn để đối phó với trường hợp này.

Trong đậu của bạn, chỉ cần thực hiện một đặc điểm

trait IgnoreUnknownProperties { 
    def propertyMissing(String name, value){ 
     // do nothing 
    } 
} 

class Person implements IgnoreUnknownProperties { 
    String name 
} 

map = ["name": "haha", "extra": "test"] 
Person p = new Person(map) 

println p.name 
+0

Cách thực sự thanh lịch để giải quyết vấn đề này. –

+0

Tôi đã sử dụng phương pháp này thành công trong bảng điều khiển Groovy (v2.4.8) nhưng khi tôi cố gắng làm tương tự trong dự án Groovy của tôi, tôi nhận được một java.lang.VerifyError phàn nàn về chữ ký phương thức của propertyMissing ?! Có ai có một ý tưởng tại sao? – Emil

1

Tương tự như @ JiankuanXing của câu trả lời (mà là một câu trả lời hoàn hảo :)), nhưng thay vì sử dụng trait lớp lon của bạn kéo dài Expando và thêm các phương pháp propertyMissing :

class Banana extends Expando { 
    String name 

    def propertyMissing(name, value) { 
     // nothing 
    } 
} 
def params = [name:'someGuy', age:13] 
new Banana(params) 

Việc sử dụng trait phù hợp với trường hợp này có thể tốt hơn vì nó cho phép hành vi compo sition và bạn có thể thêm trait cho tất cả các đối tượng lớp cần nó. Tôi chỉ thêm tùy chọn này vì Expando có thể được sử dụng kể từ groovy 1.5 phiên bản trong khi traits được giới thiệu trong groovy 2.3.

Hy vọng nó giúp,

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