मैं कक्षाओं, अच्छी तरह से, अपरिवर्तनीय बनाने के लिए एक आसान तरीका के रूप में ग्रोवी के @Immutable
एएसटी परिवर्तन की सलाह देता हूं। यह हमेशा अन्य ग्रोवी कक्षाओं के साथ ठीक काम करता है, लेकिन किसी ने हाल ही में मुझसे पूछा कि क्या मैं उन वर्गों को जावा कोड में मिला सकता हूं। मैंने हमेशा सोचा कि जवाब हाँ था, लेकिन मैं एक झगड़ा मार रहा हूँ। सब कुछ काम करता है के रूप में उम्मीदजावा में ग्रोवी @ इमटेबल वर्ग
import groovy.transform.Immutable
@Immutable
class User {
int id
String name
}
अगर मैं एक JUnit परीक्षण ग्रूवी में लिखा का उपयोग कर यह परीक्षण,:
import org.junit.Test
class UserGroovyTest {
@Test
void testMapConstructor() {
assert new User(name: 'name', id: 3)
}
@Test
void testTupleConstructor() {
assert new User(3, 'name')
}
@Test
void testDefaultConstructor() {
assert new User()
}
@Test(expected = ReadOnlyPropertyException)
void testImmutableName() {
User u = new User(id: 3, name: 'name')
u.name = 'other'
}
}
मैं एक साथ भी ऐसा ही कर सकते हैं
मैं अपरिवर्तनीय User
वर्ग है कहो जावा में लिखित जुनीट टेस्ट:
आयात स्थिर org.junit.Assert। *;
import org.junit.Test;
public class UserJavaTest {
@Test
public void testDefaultCtor() {
assertNotNull(new User());
}
@Test
public void testTupleCtor() {
assertNotNull(new User(3, "name"));
}
@Test
public void testImmutableName() {
User u = new User(3, "name");
// u.setName("other") // Method not found; doesn't compile
}
}
यह काम करता है, हालांकि क्षितिज पर परेशानी होती है। IntelliJ 15 को new User()
पर कॉल पसंद नहीं है, दावा करते हुए कि निर्माता नहीं मिला है। इसका मतलब यह भी है कि आईडीई लाल रंग को लाल रंग में रेखांकित करता है, जिसका अर्थ है कि इसमें संकलन त्रुटि है। परीक्षण वैसे भी गुजरता है, जो थोड़ा अजीब है, लेकिन ऐसा ही हो।
यदि मैं सीधे जावा कोड में User
कक्षा का उपयोग करने का प्रयास करता हूं, तो चीजें अजीब लगती हैं।
public class UserDemo {
public static void main(String[] args) {
User user = new User();
System.out.println(user);
}
}
फिर इंटेलिजे खुश नहीं है, लेकिन संकलित और चलाता है। उत्पादन सब बातों की, है:
User(0)
कि अजीब है, क्योंकि हालांकि @Immutable
बदलना एक toString
विधि उत्पन्न करता है, मैं नहीं बल्कि यह उत्पादन की उम्मीद दोनों गुण दिखाने के लिए। फिर भी, ऐसा इसलिए हो सकता है क्योंकि name
संपत्ति शून्य है, इसलिए यह आउटपुट में शामिल नहीं है।
अगर मैं टपल निर्माता इस्तेमाल करने की कोशिश:
public class UserDemo {
public static void main(String[] args) {
User user = new User(3, "name");
System.out.println(user);
}
}
मैं आउटपुट के रूप में
User(0, name)
मिलता है, कम से कम इस बार (कभी कभी यह बिल्कुल काम नहीं करता है)।
फिर मैंने एक ग्रैडल बिल्ड फ़ाइल जोड़ा।
> gradle test
error: cannot find symbol
User user = new User(...)
^
मैं आमतौर पर इस तरह पार संकलन मुद्दों को ठीक: यदि मैं src\main\java
(परीक्षण के लिए एक ही लेकिन इसके बजाय test
फ़ोल्डर का उपयोग) के तहत src\main\groovy
तहत ग्रूवी वर्गों और जावा वर्गों डाल, मैं तुरंत एक संकलन मुद्दा मिल सब कुछ के लिए ग्रोवी कंपाइलर का उपयोग करने की कोशिश कर। अगर मैं src\main\java
के तहत दोनों कक्षाएं डालता हूं, तो कुछ भी नहीं बदलता है, जो एक बड़ा आश्चर्य नहीं है। लेकिन अगर मैं src\main\groovy
के तहत दोनों वर्गों में कहें, तो मैं इस compileGroovy
चरण के दौरान मिलता है:
> gradle clean test
error: constructor in class User cannot be applied to the given types;
User user = new User(3, "name");
required: no arguments
found: int,String
reason: actual and formal arguments differ in length
हुह। इस बार यह ट्यूपल कन्स्ट्रक्टर पर ऑब्जेक्ट कर रहा है, क्योंकि ऐसा लगता है कि इसमें केवल एक डिफ़ॉल्ट कन्स्ट्रक्टर है। मुझे पता है कि ट्रांसफॉर्म एक डिफ़ॉल्ट, नक्शा-आधारित, और एक ट्यूपल कन्स्ट्रक्टर जोड़ता है, लेकिन शायद वे जावा कोड के लिए उन्हें देखने के लिए समय में उत्पन्न नहीं हो रहे हैं।
संयोग से, अगर मैं फिर से जावा और ग्रूवी वर्गों को अलग, और मेरे Gradle के लिए निम्न जोड़ने का निर्माण:
sourceSets {
main {
java { srcDirs = []}
groovy { srcDir 'src/main/java' }
}
}
मैं एक ही त्रुटि मिलती है। अगर मैं sourceSets
ब्लॉक नहीं जोड़ता, तो मुझे User
कक्षा पहले से त्रुटि नहीं मिली है।
तो नीचे की रेखा यह है कि @Immutable
ग्रोवी क्लास को मौजूदा जावा सिस्टम में जोड़ने का सही तरीका क्या है? क्या जावा को देखने के लिए समय पर रचनाकारों को उत्पन्न करने का कोई तरीका है?
मैं वर्षों से जावा डेवलपर्स को ग्रोवी प्रस्तुतिकरण कर रहा हूं और कह रहा हूं कि आप यह कर सकते हैं, केवल समस्याओं में भाग लेने के लिए। किसी भी तरह से चेहरे को बचाने में मेरी मदद करें। :)
विशेष रूप से एएसटी रूपांतरणों के साथ ग्रोवी की बात आती है तो आईडीई झूठी-नकारात्मकता देते हैं। क्रॉस-संकलन मुद्दे के लिए आप दो अलग-अलग परियोजनाओं, एक जावा और एक ग्रोवी होने का प्रयास कर सकते हैं। यदि यह अभी भी एक अनसुलझा सवाल है, तो मैं इसे सुबह में एक भंवर दे दूंगा। यह वास्तव में ऐसा लगता है जैसे इसे काम करना चाहिए। – cjstehno
क्या व्यवहार '@ CompileStatic' के साथ समान है? – dmahapatro
'@ कंपाइलस्टैटिक 'कुछ भी नहीं बदलता – kousen