2012-12-15 7 views
13

अगर मैं एक मनमाना वर्ग कि तुलनीय को लागू नहीं करता है, और एक treeset के रूप में उपयोग करने की कोशिश बनाने के लिए, यह रन टाइम पर एक अपवाद जब एक वस्तु डाला जाता है फेंकता है:गैर-तुलनात्मक वर्ग के साथ ट्रीसेट बनाना: संकलन-समय त्रुटि के बजाए रन-टाइम अपवाद क्यों?

public class Foo { 
} 

public TreeSet<Foo> fooSet = new TreeSet<Foo>(); 
fooSet.add(new Foo()); // Throws a ClassCastException exception here: Foo is not comparable 

मुझे कोई जावा विशेषज्ञ हूँ, लेकिन इसके बारे में कुछ गतिशील रूप से टाइप किया गया था (एला पायथन) जिस तरह से मैं उम्मीद नहीं कर रहा था। क्या ट्रीसेट के कार्यान्वयन के लिए कोई तरीका नहीं है कि यह निर्दिष्ट करने के लिए कि उसके सामान्य प्रकार तर्क को तुलनात्मक लागू करना चाहिए ताकि इसे संकलित समय पर पकड़ा जा सके? गैर-जेनेरिक फ़ंक्शन इंटरफेस को तर्क के रूप में ले सकते हैं; जेनेरिक के साथ भी यही संभव नहीं है?

उत्तर

21

TreeSet कि जिस तरह से कार्यान्वित किया जाता है, क्योंकि आप एक Comparator, जिस स्थिति में तत्वों Comparable होने की जरूरत नहीं है alternatively provide कर सकते हैं। एकाधिक वर्गों में कार्यान्वयन को विभाजित किए बिना दोनों व्यवहारों का समर्थन करने का एकमात्र तरीका रनटाइम चेक शामिल करना था - यह केवल उस वर्ग के लेखक (ओं) द्वारा डिज़ाइन निर्णय था।

सार्वजनिक रचनाकारों के बजाय TreeSet के लिए कारखाने के तरीकों का खुलासा करना कठोर जेनेरिक प्रकार की बाधाओं का उपयोग करके संकलन समय जांच को बनाए रखने का एक तरीका रहा होगा, लेकिन यह मूल संग्रह से सार्वजनिक ब्रेक एपीआई के उद्घाटन के सम्मेलन के ब्रेक से होता है और इसके कार्यान्वयन कक्षाओं के लिए रचनाकारों की प्रतिलिपि बनाएँ। जैसा कि आपने अपनी टिप्पणी में उल्लेख किया है, Guava अपने संग्रह के साथ फैक्ट्री मार्ग चलाता है और आईएमएचओ इसके लिए बेहतर है।

+2

धन्यवाद - यह सही समझ में आता है। वास्तव में, मुझे लगता है कि Google की गुवा पुस्तकालय में एक [TreeMultiSet] है (http://google-collections.googlecode.com/svn/trunk/javadoc/com/google/common/collect/TreeMultiset.html#create (java.util .Comparator)) वर्ग जिसे आप वर्णन करते हैं, जैसा कि आप वर्णन करते हैं - दो कारखानों के साथ, जिनमें से एक सामान्य जेनेरिक विस्तार की आवश्यकता होती है, और इनमें से एक उचित टाइप किए गए तुलनाकर्ता को लेता है। मुझे लगता है कि उन्होंने समय संकलित करने के लिए अधिक चेक लाने के लिए डिज़ाइन "बग" को ठीक करने का निर्णय लिया है। – uscjeremy

+2

हाँ, यह विशेष रूप से परेशानी है कि 'ट्रीसेट' असफल नहीं हो सकता है जब तक आप वास्तव में एक तत्व नहीं डालते जो काम नहीं करता है, मिरर टाइप करने के लिए धन्यवाद। सौभाग्य से यह कम से कम एक "मुझे एक बार मूर्ख" तरह की विफलता है, लेकिन अभी भी संकलन समय पर इसे पकड़ने के लिए परेशान नहीं है। –

+3

मुझे लगता है कि यह वास्तव में बदतर है - अगर मेरे पास 'फू' के उप-वर्गों का समूह था, और उनमें से कुछ केवल तुलनात्मक लागू किए गए थे, तो 'एड' एक अपवाद नहीं फेंक देगा जब तक कि गैर-तुलनात्मक अंत में से कोई एक अंततः डाला न जाए। कौन जानता है कि आखिर में कब होगा? यह एक निराशाजनक डिज़ाइन विकल्प है: मैं जावा को गतिशील रूप से टाइप की गई भाषाओं पर आंशिक रूप से उपयोग करता हूं ताकि प्रत्येक कोड पथ निष्पादित होने तक टाइपिंग न होने की अराजकता से दूर हो सके! – uscjeremy

संबंधित मुद्दे