#خليك_في_البيت
من اجل سلامتك وسلامة عائلتك يرجى اتباع إرشادات الصحية من المسؤلين

موقع عز تكنولوجي يتمني لكم الصحه والعافيه من كورونا

الفرق بين var و val


كما قال العديد من الآخرين ، لا يمكن استبدال الكائن المعين إلى val ، ويمكن للكائن المعين إلى var. ومع ذلك ، يمكن تعديل الكائن المذكور. فمثلا:
class A(n: Int) {
  var value = n
}

class B(n: Int) {
  val value = new A(n)
}

object Test {
  def main(args: Array[String]) {
    val x = new B(5)
    x = new B(6) // Doesn't work, because I can't replace the object created on the line above with this new one.
    x.value = new A(6) // Doesn't work, because I can't replace the object assigned to B.value for a new one.
    x.value.value = 6 // Works, because A.value can receive a new object.
  }
}
لذا ، على الرغم من أننا لا نستطيع تغيير الكائن المعين إلى x ، يمكننا تغيير حالة هذا الكائن. في جذرها ، ومع ذلك ، كان هناك فار.

الآن ، الثبات هو شيء جيد لأسباب عديدة. أولاً ، إذا لم يقم كائن بتغيير الحالة الداخلية ، فلا داعي للقلق إذا قام جزء آخر من التعليمات البرمجية بتغييره. فمثلا:
x = new B(0)
f(x)
if (x.value.value == 0)
  println("f didn't do anything to x")
else
  println("f did something to x")
يصبح هذا مهمًا بشكل خاص مع الأنظمة متعددة مؤشرات الترابط. في نظام متعدد مؤشرات الترابط ، يمكن أن يحدث ما يلي::
x = new B(1)
f(x)
if (x.value.value == 1) {
  print(x.value.value) // Can be different than 1!
}
إذا كنت تستخدم فال حصريًا ، ولا تستخدم سوى هياكل البيانات الثابتة (أي تجنب الصفائف وكل شيء في scala.collection.mutable ، وما إلى ذلك) ، يمكنك أن تطمئن إلى أن هذا لن يحدث. أي أنه ما لم يكن هناك كود ، ربما حتى إطار عمل ، يقوم بحيل انعكاسية - يمكن للانعكاس أن يغير القيم "غير القابلة للتغيير" ، للأسف.

هذا سبب واحد ، ولكن هناك سبب آخر لذلك. عند استخدام var ، يمكنك إغراء إعادة استخدام var نفسه لأغراض متعددة. هذا لديه بعض المشاكل:

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

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

على سبيل المثال ، خذ قائمة انتظار غير قابلة للتغيير. عندما تقوم بإدراج أو dequeuethings فيه ، تحصل على كائن قائمة انتظار جديد. فكيف ستقوم بمعالجة جميع العناصر الموجودة فيه؟

سأتناول ذلك بمثال. لنفترض أن لديك قائمة انتظار من الأرقام ، وتريد إنشاء رقم منها. على سبيل المثال ، إذا كان لدي قائمة انتظار مع 2 ، 1 ، 3 ، بهذا الترتيب ، فأنا أريد استعادة الرقم 213. لنحلها أولاً مع متغير.
def toNum(q: scala.collection.mutable.Queue[Int]) = {
  var num = 0
  while (!q.isEmpty) {
    num *= 10
    num += q.dequeue
  }
  num
}
هذا الرمز سريع وسهل الفهم. عيبه الرئيسي هو أن قائمة الانتظار التي يتم تعديلها يتم تعديلها من قبل toNum ، لذلك يجب عليك عمل نسخة منها مسبقًا. هذا هو نوع من إدارة الكائنات التي تجعلك الثبات خاليًا منها.

الآن ، دعنا نغطيه إلى حد كبير.
def toNum(q: scala.collection.immutable.Queue[Int]) = {
  def recurse(qr: scala.collection.immutable.Queue[Int], num: Int): Int = {
    if (qr.isEmpty)
      num
    else {
      val (digit, newQ) = qr.dequeue
      recurse(newQ, num * 10 + digit)
    }
  }
  recurse(q, 0)
}
لأنني لا أستطيع إعادة استخدام بعض المتغيرات لتتبع رقمي ، كما في المثال السابق ، أحتاج إلى اللجوء إلى العودية. في هذه الحالة ، هو عائد الذيل ، والذي يتميز بأداء جيد. ولكن هذا ليس هو الحال دائمًا: في بعض الأحيان لا يوجد حل جيد للتكرار الخلفي (سهل القراءة).

ومع ذلك ، لاحظ أنه يمكنني إعادة كتابة هذا الرمز لاستخدام غير قابل للتغيير. قائمة انتظار وفار في نفس الوقت! فمثلا:
def toNum(q: scala.collection.immutable.Queue[Int]) = {
  var qr = q
  var num = 0
  while (!qr.isEmpty) {
    val (digit, newQ) = qr.dequeue
    num *= 10
    num += digit
    qr = newQ
  }
  num
}
لا يزال هذا الرمز فعالًا ، ولا يتطلب التكرار ، ولا داعي للقلق سواء كان عليك إنشاء نسخة من قائمة الانتظار الخاصة بك أم لا قبل الاتصال بـ Num. بطبيعة الحال ، تجنبت إعادة استخدام المتغيرات لأغراض أخرى ، ولا يراها أي كود خارج هذه الوظيفة ، لذلك لا داعي للقلق بشأن تغير قيمها من سطر إلى آخر - إلا عندما أفعل ذلك صراحة.

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

أنا شخصياً أعتقد أن سكالا يحقق التوازن الصحيح في الوقت الحالي. انها ليست مثالية ، حتى الآن. أعتقد أن كل من كلوجور وهاسكيل لديهما مفاهيم مثيرة للاهتمام للغاية لم تتبناها سكالا ، لكن سكالا لديها نقاط القوة الخاصة بها أيضًا. سنرى ما سيحدث في المستقبل.

إضافة تعليق

Iklan Tengah Artikel 2

Iklan Bawah Artikel

info إنضم إلى قناتنا عبر youtube