मंशा है कि किसी भी वर्ग X
कि TaskCollection
फैली हुई है, जब एक GroupBy ऑपरेशन है के लिए प्रदर्शन किया गया, नक्शा मूल्यों के लिए उपयोग किया गया संग्रह वर्ग X
के उदाहरण भी हैं। उनके GroupBy नक्शा मूल्यों के लिए एक और TaskCollection
वर्ग का उपयोग करने का
class Task {}
class Assertion extends Task {}
abstract class TaskCollection<E extends Task, C extends TaskCollection<E, C>> extends HashSet<E> {
<K> Map<K, C> groupBy(Function<E, K> groupingFunction) {
return this.stream()
.collect(Collectors.groupingBy(
groupingFunction,
Collectors.toCollection(this.collectionSupplier())
));
}
protected abstract Supplier<C> collectionSupplier();
}
class AssertionCollection extends TaskCollection<Assertion, AssertionCollection> {
@Override
protected Supplier<AssertionCollection> collectionSupplier() {
return AssertionCollection::new;
}
}
उपवर्गों सूचना है कि TaskCollection
की परिभाषा से ऊपर काफी नहीं रुकती:
उस मामले में, निकटतम आपको लगता है कि करने के लिए प्राप्त कर सकते हैं निम्नलिखित की तरह कुछ है । उदाहरण के लिए यह भी संकलन होगा:
class AssertionCollectionOther extends TaskCollection<Assertion, AssertionCollectionOther> {...}
class AssertionCollection extends TaskCollection<Assertion, AssertionCollectionOther> {...}
दुर्भाग्य से यह कम से कम अब के लिए, इस तरह के एक बाधा लागू करने के लिए संभव नहीं है, जैसा कि आप वर्ग सी प्रकार पैरामीटर वाइल्डकार्ड में घोषित किया जा रहा है के संदर्भ में नहीं कर सकता।
यदि आप मान सकते हैं कि वंश के पास आपूर्तिकर्ता के रूप में पैरामीटर मुक्त कन्स्ट्रक्टर है तो आप collectionSupplier
के लिए एक डिफ़ॉल्ट कार्यान्वयन प्रदान कर सकते हैं। आपके द्वारा भुगतान की जाने वाली कीमत को "अनचेक" चेतावनी (वास्तविक समस्या नहीं) को चुप करने की आवश्यकता है और यह अनुपालन वर्ग नहीं है (पैरामीटर मुक्त कन्स्ट्रक्टर प्रदान नहीं कर रहा है) संकलन समय पर असफल नहीं होगा लेकिन रन-टाइम पर जो कम आदर्श है :
import java.util.function.*;
import java.util.*;
import java.util.stream.*;
class Task {}
class Assertion extends Task {}
class TaskCollection<E extends Task, C extends TaskCollection<E, C>> extends HashSet<E> {
<K> Map<K, C> groupBy(Function<E, K> groupingFunction) {
return this.stream()
.collect(Collectors.groupingBy(
groupingFunction,
Collectors.toCollection(this.collectionSupplier())
));
}
@SuppressWarnings("unchecked")
protected Supplier<C> collectionSupplier() {
return() -> {
try {
return (C) this.getClass().newInstance();
} catch (Exception ex) {
throw new RuntimeException(String.format("class %s is not a proper TaskCollection", this.getClass()), ex);
}
};
}
}
class AssertionCollection extends TaskCollection<Assertion, AssertionCollection> {
// This override is not needed any longer although still could
// be included in order to produce a slightly faster
// customized implementation:
//@Override
//protected Supplier<AssertionCollection> collectionSupplier() {
// return AssertionCollection::new;
//}
}
आप यह घोषणा करते हैं collectionSupplier
final
के रूप में आप को प्रभावी ढंग से हमेशा चेतावनी के साथ अपने ही वर्ग के उदाहरण वापस जाने के लिए है कि एक है, तो गैर-भावना, घोषणा जैसे class AssertionCollection extends TaskCollection<Assertion, AssertionCollectionOther>
अभी भी संकलन और रन-टाइम का उत्पादन करेगा उपवर्गों मजबूर होना पड़ा सड़क के नीचे अपवाद कास्ट।
आपके कार्यान्वयन के बारे में एक टिप्पणी: ऐसा लगता है कि 'टास्ककोलेक्शन' में 'टास्ककोलेक्शन' की तुलना में 'हैशसेट' बेहतर समझ में आता है, 'हैशसेट' है। 'हैशसेट' का उपयोग एक कार्यान्वयन विस्तार की तरह लगता है। क्या आपको 'हैशसेट' से उत्तराधिकारी होने की आवश्यकता है? – scottb