سؤال

ولقد كنت أتساءل عما إذا كان <م> شفافة التحويلات 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 أي شخص؟) الاستفادة من قوة implicits.

هل كانت مفيدة؟

المحلول

وأعتقد أن أكثر طريقة "صريحة" للقيام تحويلات ضمنية هو أفضل بكثير من حيث القراءة من واحد شفافة تماما، على الأقل في هذا المثال.

في رأيي، وذلك باستخدام implicits بشفافية كاملة من نوع A لكتابة B على ما يرام عندما يمكنك <م> دائما عرض كائن من نوع A بأنها قادرة على أن تستخدم كلما وهناك حاجة كائن من نوع B . على سبيل المثال، التحويل الضمني من String إلى RandomAccessSeq[Char] دائما المنطقي - يمكن دائما، من الناحية النظرية، أن ينظر في String باعتباره سلسلة من الأحرف (في C، وهي السلسلة <م> فقط سلسلة من الأحرف، فمثلا). دعوة إلى x.foreach(println) المنطقي ل<م> جميع Strings.

ومن جهة أخرى، يجب استخدام التحويلات أكثر وضوحا عندما كائن من نوع A يمكن <م> أحيانا استخدامها ككائن من نوع B. في المثال الخاص بك، دعوة إلى foo("bar") لا معنى ويلقي خطأ. كما لم يكن لديك سكالا التحقق من الاستثناءات، دعوة إلى foo(s.toDate) بشكل واضح يشير إلى أن قد يكون هناك استثناء القيت (s قد لا يكون تاريخا صالحا). أيضا، foo("bar".toDate) يبدو بوضوح خطأ، في حين تحتاج إلى مراجعة وثائق لمعرفة لماذا foo("bar") قد تكون خاطئة. مثال على ذلك في المكتبة القياسية سكالا هو التحويلات من Strings إلى Ints، عبر طريقة toInt من المجمع RichString (يمكن أن ينظر إليه Strings كما Ints، ولكن ليس <م> كل الوقت ).

نصائح أخرى

وعند إجراء التحويل الضمني من X إلى Y (مثل التحويل من سلسلة إلى التسجيل أعلاه)، تقوله أساسا أنه لو كان لديك السيطرة الكاملة على الكتابة X في المقام الأول، وكنت قد قدمت X تنفيذ أو أن يكون فئة فرعية من Y.

إذا كان من المنطقي لX لتنفيذ Y، ثم يضاف التحويل. إذا لم يحدث ذلك، ثم ربما انها ليست مناسبة. على سبيل المثال، فمن المنطقي لسلسلة لتنفيذ RandomAccessSeq [شار]، ولكن ربما لا معنى لسلسلة لتنفيذ التسجيل (على الرغم من سلسلة تنفيذ StringDate يبدو غرامة).

و(أنا في وقت متأخر قليلا، وFlaviu له إجابة ممتازة، ولكن كنت أريد أن أضيف تعليقا حول كيفية أفكر implicits).

مرخصة بموجب: CC-BY-SA مع الإسناد
لا تنتمي إلى StackOverflow
scroll top