سكالا الخيارات استخدام الضمني
سؤال
ولقد كنت أتساءل عما إذا كان <م> شفافة م> التحويلات implicit
حقا هذه فكرة جيدة، وما إذا كان قد تكون في الواقع أفضل لاستخدام implicits أكثر، أم، <م> صراحة م>. على سبيل المثال، لنفترض أن لدي الطريقة التي يقبل Date
كمعلمة ولدي التحويل الضمني الذي يتحول String
إلى Date
:
implicit def str2date(s: String) : Date = new SimpleDateFormat("yyyyMMdd").parse(s)
private def foo(d: Date)
وبعد ذلك بالطبع يمكن أن أدعو هذا مع تحويل implicit
شفافة:
foo("20090910")
وسيكون من الأفضل لجعل حقيقة أنني تحويل السلسلة إلى موعد أكثر وضوحا؟
class DateString(val s: String) {
def toDate : Date = new SimpleDateFormat("yyyyMMdd").parse(s)
}
implicit def str2datestr(s: String) : DateString = new DateString(s)
وحتى ذلك الحين يبدو استخدام أكثر مثل:
foo("20090910".toDate)
وميزة هذا هو أنه أوضح في وقت لاحق على ما يحدث - لقد اشتعلت بها عدة مرات الآن من التحويلات implicit
شفافة وأود أن أعرف عن وهذا الاستخدام لا يزال يسمح لنا (Option
إلى Iterable
أي شخص؟) الاستفادة من قوة implicit
s.
المحلول
وأعتقد أن أكثر طريقة "صريحة" للقيام تحويلات ضمنية هو أفضل بكثير من حيث القراءة من واحد شفافة تماما، على الأقل في هذا المثال.
في رأيي، وذلك باستخدام implicit
s بشفافية كاملة من نوع A
لكتابة B
على ما يرام عندما يمكنك <م> دائما عرض كائن من نوع A
بأنها قادرة على أن تستخدم كلما وهناك حاجة كائن من نوع B
. على سبيل المثال، التحويل الضمني من String
إلى RandomAccessSeq[Char]
دائما المنطقي - يمكن دائما، من الناحية النظرية، أن ينظر في String
باعتباره سلسلة من الأحرف (في C، وهي السلسلة <م> فقط م> سلسلة من الأحرف، فمثلا). دعوة إلى x.foreach(println)
المنطقي ل<م> جميع م> String
s.
ومن جهة أخرى، يجب استخدام التحويلات أكثر وضوحا عندما كائن من نوع A
يمكن <م> أحيانا م> استخدامها ككائن من نوع B
. في المثال الخاص بك، دعوة إلى foo("bar")
لا معنى ويلقي خطأ. كما لم يكن لديك سكالا التحقق من الاستثناءات، دعوة إلى foo(s.toDate)
بشكل واضح يشير إلى أن قد يكون هناك استثناء القيت (s
قد لا يكون تاريخا صالحا). أيضا، foo("bar".toDate)
يبدو بوضوح خطأ، في حين تحتاج إلى مراجعة وثائق لمعرفة لماذا foo("bar")
قد تكون خاطئة. مثال على ذلك في المكتبة القياسية سكالا هو التحويلات من String
s إلى Int
s، عبر طريقة toInt
من المجمع RichString
(يمكن أن ينظر إليه String
s كما Int
s، ولكن ليس <م> كل الوقت م>).
نصائح أخرى
وعند إجراء التحويل الضمني من X إلى Y (مثل التحويل من سلسلة إلى التسجيل أعلاه)، تقوله أساسا أنه لو كان لديك السيطرة الكاملة على الكتابة X في المقام الأول، وكنت قد قدمت X تنفيذ أو أن يكون فئة فرعية من Y.
إذا كان من المنطقي لX لتنفيذ Y، ثم يضاف التحويل. إذا لم يحدث ذلك، ثم ربما انها ليست مناسبة. على سبيل المثال، فمن المنطقي لسلسلة لتنفيذ RandomAccessSeq [شار]، ولكن ربما لا معنى لسلسلة لتنفيذ التسجيل (على الرغم من سلسلة تنفيذ StringDate يبدو غرامة).
و(أنا في وقت متأخر قليلا، وFlaviu له إجابة ممتازة، ولكن كنت أريد أن أضيف تعليقا حول كيفية أفكر implicits).