271. Immutable objects

אחד הקונספטים החזקים בעולם הOOP הוא הקונספט של אובייקטים שהם Immutable.

Immutable אומר בלתי ניתן לשינוי, והכוונה לאובייקטים שאנחנו יכולים לקבוע את ערכם, רק בConstructor.

לאחר שנוצר הInstance של האובייקט, האובייקט אינו בר שינוי יותר.

לדבר זה מספר יתרונות:

  • אנחנו לא צריכים לפחד שמישהו שינה לנו את האובייקט
  • במידה ואנחנו רוצים להעביר למישהו אחר את האובייקט, אנחנו לא צריכים להעביר לו עותק שלו, אלא מספיק להעביר את הReference, שהרי הוא לא יכול לשנות אותו. (הקונספט הזה מוכר בשפות מסוימות, בהן מקובל שבProperty אף פעם לא מחזירים Instance של Field, אלא רק העתק שלו)
  • מאחר והאובייקט אינו בר שינוי – אפשר ליצור איזשהו מנגנון שאחראי ליצור את האובייקטים האלה, והוא יחזיק גם Cache שלהם (כך שאם מבקשים את אותו אובייקט פעמיים, מקבלים אותו Instance). הדבר הזה מאפשר בעצם לנו בין השאר להשוות שני Instanceים של אובייקט שנוצר ממנגנון כזה, ע”י הReference שלהם. (במקום לכתוב מנגנון השוואה מתוחכם יותר, ראו גם טיפים 76-80)

אם נסתכל על הFramework, לא חסרים לנו אובייקטים שהםImmutable. ביניהם: string, DateTime, Delegate, Nullable ועוד.

אם נחשוב על זה, גם רוב הStructים שלנו בשפה הםImmutable , שהרי כאשר אנחנו מכניסים למשתנה ערך של Struct, נכנס למעשה עותק של הStruct למשתנה. (ראו גם טיפ מספר 131)

חלק מכם בוודאי חושבים עכשיו:

“string הוא Immutable? לא יכול להיות, הרי אפשר לכתוב:

1
2
string myString = "Hello ";
myString += "World";

"

אז איך זה בעצם עובד?

מה שמקובל לעשות בעבודה עם Immutable Objects הוא ליצור אובייקט חדש במקום לשנות את האובייקט הקיים. מה שבעצם קורה למשל במקרה זה הוא שהקוד מתרגם לקוד הבא:

1
2
string myString = "Hello ";
myString = myString + "World";

והאופרטור + דואג להחזיר לנו מחרוזת חדשה שהיא השרשור של שתי המחרוזות הנ"ל.

מי שבד"כ מתחיל לתכנת בC# מגלה שstring הוא Immutable בדרך טיפה כואבת: ע"י הפונקציה Replace:

1
2
string aNiceString = "They are the champions, my friend";
aNiceString.Replace("They","We");

מה שקורה זה שהקוד הזה נראה עובד, אבל בפועל הוא לא. אחרי כמה זמן של דיבוג, מגלים שReplace מחזיר string חדש השווה לתוצאה של הפעולה:

1
2
string aNiceString = "They are the champions, my friend";
aNiceString = aNiceString.Replace("They","We"); // :)

המשך יום בלי יותר מדי שינויים דרסטיים

שתף