2011-01-27 20 views
5

में विकल्प का उपयोग करने के लिए बेवकूफ तरीका मैं कुछ जावा कोड को स्कैला में परिवर्तित कर रहा हूं, कोड को यथासंभव मुहावरे बनाने की कोशिश कर रहा हूं।स्काला

तो, अब मेरे पास शून्य कोडों के बजाय विकल्पों का उपयोग करके कुछ कोड है, और मुझे आश्चर्य है कि चीजें स्केलिश हैं या मैं गलत हूं या नहीं। तो, क्या आप कृपया कोड के निम्नलिखित स्निपेट की आलोचना कर सकते हैं?

जिन क्षेत्रों में मैं विशेष रूप से प्रतिक्रिया के लिए देख रहा हूँ कर रहे हैं:

  • एक कारखाने के रूप में एक साथी वस्तु का उपयोग करते हैं, 2 विकल्प हम विकल्प या स्ट्रिंग्स पास करना चाहते हैं, इस आधार पर दे रही है: स्ट्रिंग निर्माता है ठीक है, या क्या हमें हमेशा इस तथ्य का पर्दाफाश करना चाहिए कि यह एक विकल्प है?
  • पूर्व शर्त का उपयोग: क्या इस तथ्य को ज़ोर देने के बेहतर तरीके हैं कि अल्फा 3 कोड और नाम अनिवार्य हैं, और अल्फा2Cोड के लिए एक गैर-शून्य विकल्प पारित होना चाहिए? (मैं स्ट्रिंग यूटिल के लिए Guava का सहारा ले रहा हूं, क्योंकि मुझे स्कैला एपीआई में कुछ भी नहीं मिला है)
  • हैशकोड, बराबर और टूस्ट्रिंग का कार्यान्वयन। गुवा में फिर से बराबर और toString प्रतिनिधि, जबकि बराबर पैटर्न मिलान का उपयोग करता है। क्या कोई और अधिक तरीका है?
  • मुझे पता है कि मैं केस क्लास का उपयोग कर सकता था, जो डिफ़ॉल्ट कार्यान्वयन करता था, लेकिन मुझे ज्यादातर सीखने में दिलचस्पी है कि मुझे उन मामलों के लिए कैसे लागू करना चाहिए जहां केस कक्षाओं का उपयोग नहीं किया जा सकता है।

बहुत बहुत धन्यवाद!

package com.sirika.openplacesearch.api.language 

import com.google.common.base.Objects 
import com.google.common.base.Strings 

object Language { 
    def apply(name : String, alpha3Code : String, alpha2Code : Option[String]) = new Language(name, alpha3Code, alpha2Code) 
    def apply(name : String, alpha3Code : String, alpha2Code : String = null) = new Language(name, alpha3Code, Option(alpha2Code)) 
    def unapply(l : Language) = Some(l.name, l.alpha3Code, l.alpha2Code) 
} 


class Language(val name : String, val alpha3Code : String, val alpha2Code : Option[String]) { 
    require(!Strings.isNullOrEmpty(alpha3Code)) 
    require(!Strings.isNullOrEmpty(name)) 
    require(alpha2Code != null) 

    override def hashCode(): Int = Objects.hashCode(alpha3Code) 

      override def equals(other: Any): Boolean = other match { 
     case that: Language => this.alpha3Code == that.alpha3Code 
     case _ => false 
    } 

    override def toString() : String = Objects.toStringHelper(this) 
     .add("name", name)  
     .add("alpha3", alpha3Code) 
     .add("alpha2", alpha2Code) 
     .toString() 
} 
+1

"चाल" करने के लिए विकल्प का उपयोग कर केवल उपयोग विकल्प है और एक ही ;-) बेशक ऐसा करने के लिए नहीं है उपभोक्ता के लिए मजबूर जावा (ick!) से निपटने पर हमेशा व्यावहारिक। एसओ में आपका स्वागत है –

+0

मुझे लगता है कि आवश्यकता नहीं है (अल्फा2Cोड! = नल) कभी भी असफल हो सकता है क्योंकि अल्फा2Cोड एक विकल्प – Azzie

उत्तर

4

मुझे लगता है कि आपको कारखाने विधि में केवल Option[String] का खुलासा करना चाहिए। उदाहरण के लिए, मैं, आपकी लाइब्रेरी के उपयोगकर्ता के रूप में, खुद से यह भी पूछूंगा कि मुझे किस फैक्ट्री विधि का उपयोग करना चाहिए। और शायद मैं विकल्प का उपयोग करूंगा।

स्कैला हमें अपने जीवन को आसान बनाने के लिए पर्याप्त टूल प्रदान करता है। उदाहरण के लिए आप इस तरह के विकल्प के लिए डिफ़ॉल्ट का उपयोग कर सकते हैं:

def apply(name: String, alpha3Code: String, alpha2Code: Option[String] = None) = 
new Language(name, alpha3Code, alpha2Code) 

अगर मैं, फिर से अपने पुस्तकालय के उपयोगकर्ता के रूप में, Some में हर बार लपेटकर बिना सिर्फ स्ट्रिंग पास करना चाहते हैं, मैं इस तरह अपने ही निहित रूपांतरण लिख सकते हैं :

implicit def anyToOption[T](t: T): Option[T] = Some(t) 

या यहाँ तक कि (यदि मैं व्यक्तिगत रूप से nulls का उपयोग करें):

implicit def anyToOption[T](t: T): Option[T] = 
if (t == null) None else Some(t) 

लेकिन मेरा मानना ​​है कि, यदि आप विकल्प को लागू है, यह अपने एपीआई अधिक ठोस और स्पष्ट कर देगा।

+3

असल में, ऑब्जेक्ट को 'विकल्प' में लपेटने का एक आसान तरीका है, जैसे' शून्य 'मान' कोई नहीं 'बन जाएगा: 'विकल्प (टी)' ('कुछ (टी)' – Madoc

4

आपको null से बचना चाहिए जब तक कि इसका कोई अच्छा कारण न हो। जैसा कि है, आप इसे अभी लिखा होगा:

def apply(name : String, alpha3Code : String, alpha2Code : String) = new Language(name, alpha3Code, Option(alpha2Code)) 
def apply(name : String, alpha3Code : String) = new Language(name, alpha3Code, None) 

पूर्व शर्त ठीक है। आप इसे इस तरह लिख सकते हैं:

require(Option(alpha3Code) exists (_.nonEmpty)) 
require(Option(name) exists (_.nonEmpty)) 

हालांकि, कोई सुधार आवश्यक नहीं है।

String में hashCode है, इसलिए मुझे समझ में नहीं आता कि आप alpha3Code.hashCode पर कॉल करने के बजाय हैश कोड उत्पन्न करने के लिए एक और विधि क्यों बुला रहे हैं। मुझे लगता है कि स्कैला एपीआई में कुछ है, हालांकि। निश्चित नहीं।

equals कोड जब तक आप अपने वर्ग sealed या final बनाने के एक canEqual विधि होनी चाहिए,। प्रतिमान मिलान काफी जिस तरह से यह करना है, हालांकि आप इसे इस एक निकालने की उपस्थिति को देखते हुए की तरह लिख सकता:

case Language(_, `alpha3Code`, _) => true 

लेकिन जिस तरह से आप यह लिखा काफी जिस तरह से यह आम तौर पर लिखा गया है।

+0

के बजाय अन्य उत्तर इस तथ्य पर जोर देते हैं कि मुझे वास्तव में उपभोक्ता को विकल्प निर्माता का उपयोग करने के लिए मजबूर होना चाहिए। क्या आप उस कथन से सहमत हैं? –

+0

हैशकोड के संबंध में, यह सच है कि इस मामले में, मैं सीधे अल्फा 3Code.hashCode का उपयोग कर सकता था, मैंने इसके बारे में भी सोचा नहीं था क्योंकि मेरे पास हमेशा जावा सिंटैक्स का उपयोग करने की आदत है, जो कई चाबियाँ जोड़ने की अनुमति देता है: ऑब्जेक्ट्सशैशकोड (अल्फा 3 कोड, नाम) –

+0

और canEqual विधि से संबंधित अच्छा बिंदु। मुझे इसके बारे में पता नहीं था। उन लोगों के लिए जो canEqual के बारे में नहीं जानते हैं, आप http://books.google.com/books?id=MFjNhTjeQKkC&pg=PA555&lpg=PA555&dq=scala+canEqual+method&source=bl&ots=FKukUGGNvo&sig=0rF3cRgwHVGZ22ggxX5j23nM32w&hl=hi&ei=As1CTaWhMoPGlQfknZ35Dw&sa= का उल्लेख कर सकते हैं एक्स और ओआई = book_result और सीटी = परिणाम और resnum = 3 और ved = 0CCcQ6AEwAg # v = onepage और q = scala% 20canEqual% 20method & f = false –

-1

मुझे विकल्प पसंद नहीं हैं - वे संकेतों का एक स्तर जोड़ते हैं जो कई मामलों में अनावश्यक और भ्रमित है। मैं नल को और भी नापसंद करता हूं, इसलिए मैं समझता हूं कि अक्सर विकल्पों का उपयोग उचित है। हालांकि, आपको हमेशा यह देखना चाहिए कि इंटरफ़ेस में Option के उपयोग को समाप्त करने का एक और प्राकृतिक तरीका है या नहीं।

डिफ़ॉल्ट पैरामीटर या अलग अधिभार अक्सर एक बेहतर विकल्प होते हैं। तो मैं इस तरह अपने कोड को फिर से लिखने चाहते हैं:

package com.sirika.openplacesearch.api.language 

import com.google.common.base.Strings 
import com.google.common.base.Objects 

object Language { 
    def apply(name : String, alpha3Code : String, alpha2Code : String) = new Language(name, alpha3Code, alpha2Code) 
    def apply(name : String, alpha3Code : String) = new Language(name, alpha3Code) 
    def unapply(l : Language) = Some(l.name, l.alpha3Code, l.alpha2Code) 
} 


class Language private (val name : String, val alpha3Code : String, val alpha2Code : Option[String]) { 
    def this(name:String,alpha3Code: String ,alpha2Code:String) = this(name,alpha3Code,Option(alpha2Code)) 
    def this(name:String,alpha3Code: String) = this(name,alpha3Code,None) 

    require(!Strings.isNullOrEmpty(alpha3Code)) 
    require(!Strings.isNullOrEmpty(name)) 

    override def hashCode = alpha3Code.hashCode 

    override def equals(other: Any) = other match { 
     case that: Language => this.alpha3Code == that.alpha3Code 
     case _ => false 
    } 

    override def toString = MoreObjects.toStringHelper(this) 
     .add("name", name)  
     .add("alpha3", alpha3Code) 
     .add("alpha2", alpha2Code) 
     .toString() 
} 

Guava docs