2011-02-01 33 views
36

Thường muốn khai báo các hằng số ở đầu tập lệnh có thể được tham chiếu ở bất kỳ nơi nào khác trong tập lệnh. Trong Groovy, có vẻ như nếu bạn khai báo một hằng số bằng cách sử dụng cuối cùng thì nó không được truy cập trong phạm vi con. Giải pháp cho yêu cầu rất cơ bản và phổ biến này là gì? Cách giải quyết tôi có ngay bây giờ là tạo ra một biến không liên kết nhưng đây không phải là một hằng số và không thanh lịch.Hằng số toàn cầu trong Groovy

Trả lời

60

Groovy không thực sự có phạm vi toàn cầu. Khi bạn có một tập lệnh groovy không khai báo một lớp, nó sẽ bị mắc kẹt trong một lớp với tên của kịch bản lệnh. Vì vậy, các biến cuối cùng ở phạm vi cấp cao nhất thực sự chỉ là các trường của lớp ngầm định. Ví dụ:

// foo.groovy 
final MYCONSTANT = "foobar" 
println MYCONSTANT 

class Helper { 
    def hello() { println MYCONSTANT } // won't work 
} 
new Helper().hello() 

là nhiều hay ít tương đương với:

class foo { 
    def run() { 
     final MYCONSTANT = "foobar" 
     println MYCONSTANT 
     new Helper().hello() 
    } 
    static main(args) { 
     new foo().run() 
    } 
} 

class Helper { 
    def hello() { println MYCONSTANT } // won't work 
} 

Thật dễ dàng để xem lý do tại sao nó không hoạt động mở rộng ra. Một công việc dễ dàng xung quanh là tuyên bố "hình cầu" của bạn trong một lớp giả gọi là e.g. Hằng số, và sau đó chỉ cần nhập một tĩnh vào nó. Nó thậm chí làm việc tất cả trong một kịch bản duy nhất. Ví dụ:

import static Constants.* 

class Constants { 
    static final MYCONSTANT = "foobar" 
} 

println MYCONSTANT 

class Helper { 
    def hello() { println MYCONSTANT } // works! 
} 
new Helper().hello() 

EDIT:

Ngoài ra, kịch bản là chút của một trường hợp đặc biệt. Nếu bạn khai báo biến số không có def hoặc bất kỳ công cụ sửa đổi nào chẳng hạn như final, (nghĩa là chỉ sử dụng nó), biến đó sẽ được liên kết với toàn bộ tập lệnh. Vì vậy, trong trường hợp này:

CONSTANT = "foobar" 
println "foobar" 

CONSTANT là trong kịch bản toàn ràng buộc, nhưng trong:

final CONSTANT = "foobar" 
println "foobar" 

CONSTANT là một biến cục bộ trong phương pháp của kịch bản run(). Thông tin thêm về vấn đề này có thể được tìm thấy tại https://web-beta.archive.org/web/20150108090004/http://groovy.codehaus.org/Scoping+and+the+Semantics+of+%22def%22

+0

Hằng số phải là enums trong thế giới Java 1.5+ ... :) – Esko

+6

@Esko mọi loại hằng số phải là Enum? Ngay cả một cái gì đó như GRAVITY hoặc PI? O_o –

+0

@tim_yates: Không, enum phải chứa tất cả các hằng số có liên quan với nhau. Trong ví dụ của bạn sẽ giống như 'CelestialObjectAttributes.GRAVITY' hoặc' MathematicConstants.PI'. Đây có thể được nhập khẩu quá để bạn không phải lặp lại tên của enum và enums luôn luôn là VM (* hoặc classloader *) toàn cầu mà làm cho chúng thay thế hoàn hảo cho các hằng số toàn cầu oldschool. – Esko

18

Trong Groovy 1.8+, bạn có thể đạt được điều này bằng cách sử dụng @Field annotation:

import groovy.transform.Field 

@Field final String MY_CONSTANT = 'constant' 

def printConstant() { println MY_CONSTANT } 

printConstant() 
+1

không hoạt động từ bên trong một lớp học mặc dù: ( – Anentropic

+0

@Anentropic: đừng bỏ lỡ việc nhập khẩu ở trên "import groovy.transform.Field" – BTakacs

0

Các cách khác hiệu quả để thêm ứng dụng toàn cầu hằng mức là tuyên bố một giao diện trong gói phù hợp như

interface applicationConstants { 
//All constants goes here. 
    static final float PI = 3.14 
    String ADMIN_USER = "ADMIN" 
    Map languages = [ 
     "en": "English", 
     "hi": "Hindi", 
     "mr": "Marathi" 

    ] 
// Like above you can declare all application level code constants here. 

} 

Sử dụng hằng trong bất kỳ lớp như dưới đây,

import packageNameContainingInterface.applicationConstants // import statement. 
def adminUser = applicationConstants.ADMIN_USER 
println adminUser 
Các vấn đề liên quan