سؤال

لا يوجد الكثير من المعلومات في المواصفات على نوع AS -Divension ، وبالتأكيد لا يوجد أي شيء حول الغرض من ذلك. بخلاف "جعل تمريرة Varargs عمل" ، ما الذي يمكنني استخدامه من النوع؟ فيما يلي بعض Scala REPLIS لبناء بناء الجملة وتأثيرات استخدامه.

scala> val s = "Dave"
s: java.lang.String = Dave

scala> val p = s:Object
p: java.lang.Object = Dave

scala> p.length
<console>:7: error: value length is not a member of java.lang.Object
       p.length
         ^
scala> p.getClass
res10: java.lang.Class[_ <: java.lang.Object] = class java.lang.String

scala> s.getClass
res11: java.lang.Class[_ <: java.lang.Object] = class java.lang.String

scala> p.asInstanceOf[String].length
res9: Int = 4
هل كانت مفيدة؟

المحلول

اكتب AS -Decription هو مجرد إخبار المحول البرمجي عن النوع الذي تتوقعه من التعبير ، من جميع الأنواع الصالحة الممكنة.

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

لذا، java.lang.String extends java.lang.Object, لذلك أي String هو أيضا Object. في مثالك ، أعلنت أنك تريد التعبير s أن تعامل على أنها Object, ، ليس أ String. نظرًا لعدم وجود قيود تمنع ذلك والنوع المطلوب هو أحد الأنواع s هو, ، إنها تعمل.

الآن ، لماذا تريد ذلك؟ النظر في هذا:

scala> val s = "Dave"
s: java.lang.String = Dave

scala> val p = s: Object
p: java.lang.Object = Dave

scala> val ss = scala.collection.mutable.Set(s)
ss: scala.collection.mutable.Set[java.lang.String] = Set(Dave)

scala> val ps = scala.collection.mutable.Set(p)
ps: scala.collection.mutable.Set[java.lang.Object] = Set(Dave)

scala> ss += Nil
<console>:7: error: type mismatch;
 found   : scala.collection.immutable.Nil.type (with underlying type object Nil)
 required: java.lang.String
       ss += Nil
             ^

scala> ps += Nil
res3: ps.type = Set(List(), Dave)

يمكن أن تقوم أيضًا بإصلاح هذا عن طريق النوع s في ss إعلان ، أو يمكنك الإعلان ssنوع أن يكون Set[AnyRef].

ومع ذلك ، فإن إعلانات النوع تحقق نفس الشيء فقط طالما أنك تقوم بتعيين قيمة لمعرف. ما الذي يمكن للمرء أن يفعله دائمًا ، بالطبع ، إذا لم يهتم المرء بتضخم الكود مع معرفات طلقة واحدة. على سبيل المثال ، ما يلي لا يجمع:

def prefixesOf(s: String) = s.foldLeft(Nil) { 
  case (head :: tail, char) => (head + char) :: head :: tail
  case (lst, char) => char.toString :: lst
}

لكن هذا يفعل:

def prefixesOf(s: String) = s.foldLeft(Nil: List[String]) { 
  case (head :: tail, char) => (head + char) :: head :: tail
  case (lst, char) => char.toString :: lst
}

سيكون من السخف استخدام معرف هنا بدلاً من Nil. وعلى الرغم من أنني أستطيع الكتابة فقط List[String]() بدلاً من ذلك ، هذا ليس خيارًا دائمًا. النظر في هذا ، على سبيل المثال:

def firstVowel(s: String) = s.foldLeft(None: Option[Char]) { 
  case (None, char) => if ("aeiou" contains char.toLower) Some(char) else None
  case (vowel, _) => vowel
}

للرجوع ، هذا ما يجب أن يقوله Scala 2.7 SPEC (15 مارس 2009) عن النوع Ascription:

Expr1 ::= ...
        | PostfixExpr Ascription

Ascription ::= ‘:’ InfixType
             | ‘:’ Annotation {Annotation}
             | ‘:’ ‘_’ ‘*’

نصائح أخرى

أحد الاحتمالات هو عندما تكون الأشياء على مستوى الشبكة والبروتوكول التسلسلي ، ثم هذا:

val x = 2 : Byte

هو أنظف بكثير من

val x = 2.asInstanceOf[Byte]

النموذج الثاني هو أيضًا تحويل وقت التشغيل (لا يتم التعامل معه من قبل المترجم) ويمكن أن يؤدي إلى بعض ظروف التدفق المثيرة للاهتمام.

يمكنني استخدام نوع Ascription على الورق على الثقوب في استنتاج نوع Scala. على سبيل المثال ، يأخذ طية على مجموعة من النوع A عنصرًا أوليًا من النوع B ودالة (B ، A) => B التي يتم استخدامها لوضع عناصر المجموعة في العنصر الأولي. يتم استنتاج القيمة الفعلية للنوع B من نوع العنصر الأولي. نظرًا لأن NIL يمتد القائمة [لا شيء] ، فإن استخدامها كعنصر أولي يسبب المشاكل:

scala> val x = List(1,2,3,4)
x: List[Int] = List(1, 2, 3, 4)

scala> x.foldLeft(Nil)( (acc,elem) => elem::acc)
<console>:9: error: type mismatch;
 found   : List[Int]
 required: scala.collection.immutable.Nil.type
              x.foldLeft(Nil)( (acc,elem) => elem::acc)
                                                 ^

scala> x.foldLeft(Nil:List[Int])( (acc,elem) => elem::acc )
res2: List[Int] = List(4, 3, 2, 1)

بدلاً من ذلك ، يمكنك فقط استخدام List.Empty [int] بدلاً من NIL: قائمة [int].

scala> x.foldLeft(List.empty[Int])( (acc,elem) => elem::acc )
res3: List[Int] = List(4, 3, 2, 1)

تحرير: list.empty [a

override def empty[A]: List[A] = Nil

(مصدر)

هذا هو بشكل فعال شكل أكثر مطوّلة من NIL: قائمة [أ

قد تجد هذا الموضوع إضاءة ، إذا كانت معقدة بعض الشيء لمتابعة. الشيء المهم الذي يجب ملاحظته هو أنك تضيف تلميحات قيود إلى Checker Type - فهي تمنحك المزيد من التحكم في ما تفعله مرحلة التجميع هذه.

اكتب الاستدلال: يمكننا تخطي إعطاء اسم نوع من نوع شيء ما في الكود المصدر ، يسمى نوع الاستدلال. (على الرغم من أنه مطلوب في بعض الحالات الاستثنائية.)

اكتب AS -DISCRIPTER: أن تكون صريحًا حول نوع شيء ما يسمى نوع ASCIPPLE. ما الفرق الذي يمكن أن يحدثه؟

على سبيل المثال: Val X = 2: Byte

انظر أيضًا: 1. يمكننا إعطاء نوع العودة بوضوح إلى وظائفنا

def t1 : Option[Option[String]] = Some(None)

> t1: Option[Option[String]]

طريقة أخرى لإعلان أن هذا يمكن أن يكون:

def t2 = Some(None: Option[String])
> t2: Some[Option[String]]

هنا لم نعطي Option[Option[String]] إرجاع النوع بشكل صريح واستنتجه التحويل البرمجي على أنه Some[Option[String]]. لماذا Some[Option[String]] هو لأننا استخدمنا نوعا في التعريف.

  1. هناك طريقة أخرى يمكننا من خلالها استخدام نفس التعريف هي:

    def t3 = Some(None)

    > t3: Some[None.type]

هذه المرة لم نخبر المترجم بشكل صريح أي شيء (لا هذا defi). واستنتج تعريفنا كبعض [لا شيء.

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