213. internal access modifier

דרך נוספת להימנע מאי נעימויות של חשיפת המשתמש לדברים שהוא לא אמור להיחשף אליהם, היא להשתמש בModifier ששמו internal.

את הAccess modifier הזה אנחנו יכולים לשים על טיפוסים (בדומה לModifier ששמו public) וMemberים שלנו (בדומה לשאר הModifierים שאפשר לשים, public, private וprotected)

עצם הפיכת טיפוס או Member לinternal מונעת את חשיפתם לעולם החיצון. זה אומר שבד”כ מחוץ לAssembly שלנו, לא תהיה לנו גישה למחלקות או Memberים אלה.

הModifier יכול לעזור לנו ליצור רמת אבסטרקציה בשימוש בAssembly שלנו.

למשל, נניח שיש לנו ממשק. לממשק הזה יש מימוש. עכשיו, אם המימוש הוא public, מה שצפוי לקרות הוא שכל מי שישתמש במימוש הקונקרטי שלנו, יכתוב קוד שמשתמש בו, למרות שהוא היה יכול לכתוב את אותו הקוד שמשתמש בממשק בלבד.

לדוגמה המחלקה OracleConnection מממשת את הממשק IDbConnection:

1
2
3
4
5
6
7
8
9
10
11
public class OracleConnection : IDbConnection
{
// Constructors:
public OracleConnection()
{
// ...
}
// Implementation
// ...
}

כעת מה שסביר להניח שיקרה הוא שכל מי שישתמש בOracleConnection יכיר את המימוש הספציפי:

1
2
3
4
public void TestConnection(OracleConnection connection)
{
// ...
}

למרות שהוא היה אמור להשתמש בIDbConnection.

בעצם, החשיפה של המחלקה שלנו פגעה באיכות הקוד של המשתמשים בו. (למרות שזו גם אשמת המשתמשים)

ראו גם טיפ מספר 81.

מה שהיינו יכולים לעשות במקום, זה לעשות שהמימוש יהיה internal.

1
2
3
4
5
6
7
8
9
10
11
internal class OracleConnection : IDbConnection
{
// Constructors:
public OracleConnection()
{
// ...
}
// Implementation
// ...
}

וליצור איזושהי פונקציה שהיוצרת את המחלקה הזאת שהחתימה שלה מחזירה IDbConnection.

ככה אנחנו יכולים להיות בטוחים שרק אנחנו מכירים את הType הקונקרטי. זה גם אומר שרק אנחנו יכולים ליצור instanceים שלנו וכו’.


תכלס, אני פחות אוהב את השימוש בinternal על Memberים.

אני חושב שזה די עקום שמחלקה אחת יכולה לגשת לפונקציה פנימית של מחלקה אחרת, גם אם הן נמצאות באותו Assembly. הדבר הזה יכול ליצירת צמידות בין מחלקות, כי כעת מחלקה אחת מכירה את המימוש הפנימי של מחלקה אחרת. אם זו פונקציה שלא באמת פנימית, אין סיבה שלא להפוך אותה לpublic. אחרת, עדיף שזה יישאר protected/private.

כמובן, לפעמים אין כל כך ברירה.

לעומת זאת, אני חושב ששימוש בinternal על מחלקות או ממשקים יכול להיות לגיטימי – דוגמה אחת היא הדוגמה שרשמתי קודם: החבאת המימוש מהמשתמש.

עוד סיבה להפוך ממשק/מחלקה לinternal היא שמדובר בטיפוס שהוא באמת פנימי – כלומר, אף אחד לא אמור לדעת שהוא קיים – הוא Helper Class העוזר לנו בתוך הAssembly שלנו לממש איזשהו משהו יותר מורכב.

לדוגמה, נניח שאנחנו מממשים רשימה, ובחרנו לממש בצורה של רשימה מקושרת. נוכל ליצור מחלקה המייצגת Node של הרשימה. מי שמשתמש ברשימה שלנו לא חייב לדעת שהיא מקושרת, ולכן אנחנו יכולים להסתיר ממנו את הטיפוס של הNode. (יש דרך יותר טובה לעשות את זה, אבל זו גם דרך אפשרית)

שיהיה המשך יום פנימי טוב

שתף