2016-09-09 5 views
6

कोटलिन में, मुझे लगता है कि मैं कुछ ऑपरेटरों को + फ़ंक्शन plus(), और * फ़ंक्शन times() द्वारा ओवरराइड कर सकता हूं ... लेकिन कुछ चीजों जैसे सेट्स, पसंदीदा (सेट सिद्धांत) प्रतीकों/ऑपरेटरों मौजूद नहीं हैं। उदाहरण के लिए छेड़छाड़ के लिए A∩B और संघ के लिए A∪Bकोटलिन में, मैं कुछ मौजूदा ऑपरेटरों को ओवरराइड कर सकता हूं लेकिन नए ऑपरेटरों को बनाने के बारे में क्या?

मैं अपने स्वयं के ऑपरेटरों को परिभाषित नहीं कर सकता, ऑपरेटर के लिए किस प्रतीक का उपयोग करने के लिए कोई स्पष्ट वाक्यविन्यास नहीं है। उदाहरण के लिए मैं एक ऑपरेटर के रूप में $$ के लिए एक समारोह बनाने के लिए चाहते हैं:

operator fun String.$$(other: String) = "$this !!whatever!! $other" 
// or even 
operator fun String.whatever(other: String) = "$this !!whatever!! $other" // how do I say this is the $$ symbol?!? 

मैं दोनों के लिए एक ही त्रुटि मिलती है:

Error:(y, x) Kotlin: 'operator' modifier is inapplicable on this function: illegal function name

नियम क्या ऑपरेटर या बनाया जा सकता है अधिरोहित क्या हैं?

नोट:इस सवाल जानबूझकर लिखा है और लेखक (Self-Answered Questions) द्वारा उत्तर दिया, ताकि मुहावरेदार जवाब आमतौर पर पूछे जाने वाले Kotlin विषयों अतः में मौजूद हैं।

उत्तर

5

Kotlin केवल operators to be overridden का एक बहुत ही विशिष्ट सेट की अनुमति देता है और आप नहीं कर सकते परिवर्तन उपलब्ध ऑपरेटरों की सूची।

ऑपरेटर को ओवरराइड करते समय आपको सावधानी बरतनी चाहिए कि आप मूल ऑपरेटर की भावना, या गणितीय प्रतीक के अन्य सामान्य उपयोगों में रहने का प्रयास करते हैं। लेकिन कभी-कभी ठेठ प्रतीक उपलब्ध नहीं होता है। उदाहरण स्थापित संघ के लिए आसानी से + के रूप में इलाज कर सकते हैं क्योंकि धारणात्मक यह समझ में आता है और कहा कि एक अंतर्निहित ऑपरेटर Set<T>.plus() पहले से ही Kotlin द्वारा प्रदान की है, या आप रचनात्मक होना होगा और इस मामले के लिए एक infix function इस्तेमाल कर सकते हैं:

// already provided by Kotlin: 
// operator fun <T> Set<T>.plus(elements: Iterable<T>): Set<T> 

// and now add my new one, lower case 'u' is pretty similar to math symbol ∪ 
infix fun <T> Set<T>.u(elements: Set<T>): Set<T> = this.plus(elements) 

// and therefore use any of... 
val union1 = setOf(1,2,5) u setOf(3,6) 
val union2 = setOf(1,2,5) + setOf(3,6) 
val union3 = setOf(1,2,5) plus setOf(3,6) 

या वह अधिक स्पष्ट है के रूप में:

infix fun <T> Set<T>.union(elements: Set<T>): Set<T> = this.plus(elements) 

// and therefore 
val union4 = setOf(1,2,5) union setOf(3,6) 

और सेट ऑपरेटरों की अपनी सूची के साथ जारी रखने, चौराहे प्रतीक है तो हर प्रोग्रामर यह सोचते हैं एक फ़ॉन्ट है जहां पत्र 'एन' 012 लग रहा है के रूप में * की

infix fun <T> Set<T>.n(elements: Set<T>): Set<T> = this.intersect(elements) 

// and therefore... 
val intersect = setOf(1,3,5) n setOf(3,5) 

या के माध्यम से ऑपरेटर ओवरलोडिंग:हम साथ भाग मिल सकता है

operator fun <T> Set<T>.times(elements: Set<T>): Set<T> = this.intersect(elements) 

// and therefore... 
val intersect = setOf(1,3,5) * setOf(3,5) 

आप पहले से ही के रूप में मौजूदा मानक पुस्तकालय इन्फ़िक्स समारोह intersect() उपयोग कर सकते हैं हालांकि:

val intersect = setOf(1,3,5) intersect setOf(3,5) 

ऐसे मामलों में जहां आप कुछ नया आविष्कार कर रहे हैं, आपको निकटतम ऑपरेटर या फ़ंक्शन नाम चुनना होगा। उदाहरण enums का एक सेट को नकारने के लिए, शायद - ऑपरेटर (unaryMinus()) या ! ऑपरेटर (not()) का उपयोग करें:

enum class Things { 
    ONE, TWO, THREE, FOUR, FIVE 
} 

operator fun Set<Things>.unaryMinus() = Things.values().toSet().minus(this) 
operator fun Set<Things>.not() = Things.values().toSet().minus(this) 

// and therefore use any of... 

val current = setOf(Things.THREE, Things.FIVE) 

println(-current)    // [ONE, TWO, FOUR] 
println(-(-current))   // [THREE, FIVE] 
println(!current)    // [ONE, TWO, FOUR] 
println(!!current)   // [THREE, FIVE] 
println(current.not())  // [ONE, TWO, FOUR] 
println(current.not().not()) // [THREE, FIVE] 

सावधान रहें क्योंकि ऑपरेटर ओवरलोडिंग बहुत उपयोगी हो सकता है, या यह भ्रम और अराजकता को जन्म दे सकता।आपको कोड पठनीयता बनाए रखने के दौरान सबसे अच्छा क्या तय करना है। कभी-कभी ऑपरेटर सबसे अच्छा होता है अगर यह उस प्रतीक के लिए मानक फिट करता है, या मूल प्रतीक के समान एक इंफिक्स प्रतिस्थापन, या एक वर्णनात्मक शब्द का उपयोग कर ताकि भ्रम का कोई मौका न हो।

हमेशा Kotlin Stdlib API Reference जांचें क्योंकि आपके द्वारा इच्छित कई ऑपरेटरों को पहले ही परिभाषित किया जा सकता है, या समकक्ष विस्तार कार्य हो सकते हैं।

एक अन्य बात ...

और अपने $$ ऑपरेटर के बारे में, तकनीकी रूप से आप ऐसा कर सकते हैं:

infix fun String.`$$`(other: String) = "$this !!whatever!! $other" 

लेकिन क्योंकि तुम समारोह के नाम से बचने के लिए की जरूरत है, यह जा फोन बदसूरत करने के लिए:

val text = "you should do" `$$` "you want" 

कि सही मायने में ऑपरेटर ओवरलोडिंग नहीं है और अगर यह एक समारोह वें है केवल काम करेगा can me made infix पर।

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