שיטות הרחבה בקוטלין

1. הקדמה

קוטלין מציג את הרעיון של שיטות הרחבה - שהן דרך שימושית להרחיב את השיעורים הקיימים עם פונקציונליות חדשה ללא שימוש בירושה או צורות כלשהן של דפוס Decorator - לאחר הגדרת הרחבה. אנו יכולים להשתמש בה למעשה - כיוון שזה היה החלק של ה- API המקורי.

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

לדוגמא, ייתכן שנצטרך לבצע בריחת XML ב- חוּט. בקוד Java רגיל, נצטרך לכתוב שיטה שתוכל לבצע זאת ולקרוא לה:

מחרוזת נמלטה = escapeStringForXml (קלט);

בעוד שכתוב בקוטלין, ניתן להחליף את קטע הקוד ב:

val escaped = input.escapeForXml ()

לא רק שזה קל יותר לקריאה, אלא ש- IDE יוכלו להציע את השיטה כאפשרות השלמה אוטומטית זהה כאילו הייתה שיטה סטנדרטית ב- חוּט מעמד.

2. שיטות הרחבת ספרייה סטנדרטית

הספרייה הסטנדרטית של קוטלין מגיעה עם כמה שיטות הרחבה מחוץ לקופסה.

2.1. שיטות הרחבה להתאמת הקשר

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

מסתבר, ככל הנראה, אנו ממנפים הרחבות מבלי שנבין זאת.

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

val name = "Baeldung" val uppercase = name .let {n -> n.toUpperCase ()}

זה דומה ל מַפָּה() שיטה מ אופציונאלי אוֹ זרם שיעורים - במקרה זה, אנו מעבירים פונקציה המייצגת פעולה הממירה נתון חוּט לתוך הייצוג העליון שלה.

המשתנה שֵׁם ידוע כמקבל השיחה כי זה המשתנה ששיטת ההרחבה פועלת לפיו.

זה עובד מצוין עם מפעיל השיחות הבטוחות:

val name = maybeGetName () val uppercase = name? .let {n -> n.toUpperCase ()}

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

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

ה לָרוּץ() סיומת פועלת כמו לתת(), אך מקלט מסופק כ- זֶה ערך בתוך הבלוק שנקרא:

val name = "Baeldung" val uppercase = name.run {toUpperCase ()}

להגיש מועמדות() עובד כמו לָרוּץ(), אך הוא מחזיר מקלט במקום להחזיר את הערך מהבלוק שסופק.

בואו ננצל את זה להגיש מועמדות() לשיחות הקשורות לשרשרת:

val שפות = mutableListOf () languages.apply {add ("Java") add ("Kotlin") add ("Groovy") add ("Python")}. החל {remove ("Python")} 

שימו לב איך הקוד שלנו הופך להיות תמציתי יותר ואקספרסיבי לא צריך להשתמש במפורש זֶה אוֹ זה.

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

val שפות = mutableListOf () שפות.גם {list -> list.add ("Java") list.add ("Kotlin") list.add ("Groovy")} 

ה takeIf () הרחבה מסופקת עם פרדיקט הפועל על המקלט, ואם פרדיקט זה חוזר נָכוֹן ואז הוא מחזיר את המקלט אוֹ ריק אחרת - זה עובד באופן דומה לשילוב של מפה משותפת() ו לְסַנֵן() שיטות:

שפת val = getLanguageUsed () val coolLanguage = language.takeIf {l -> l == "Kotlin"} 

TakeUnless () הרחבה זהה ל- takeIf () אך עם הגיון הפרדיקט ההפוך.

val שפה = getLanguageUsed () val oldLanguage = language.takeUnless {l -> l == "Kotlin"} 

2.2. שיטות הרחבה לאוספים

Kotlin מוסיף מספר רב של שיטות הרחבה לאוספי Java הסטנדרטיים אשר יכולים להקל על העבודה שלנו עם הקוד.

שיטות אלה ממוקמות בפנים _Collections.kt, _Ranges.kt, ו _Sequences.kt, בנוסף ל _Arrays.kt לשיטות שוות ערך לחלות עליהן מערכים במקום זאת. (זכור שבקוטלין, מערכים ניתן לטפל באותה מידה כמו אוספים)

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

בנוסף לאוספים, קוטלין מוסיף מספר משמעותי של שיטות הרחבה ל- חוּט מעמד - מוגדר ב _ Strings.kt. אלה מאפשרים לנו לטפל מיתרים כאילו היו אוספי דמויות.

כל שיטות ההרחבה הללו פועלות יחד כדי לאפשר לנו לכתוב קוד נקי יותר וקל יותר לתחזוקה ללא קשר לסוג האוסף שאיתו אנו עובדים.

3. כתיבת שיטות ההרחבה שלנו

אז מה אם נצטרך להרחיב שיעור עם פונקציונליות חדשה - מספריית Java או Kotlin Standard או מספרייה תלויה בה אנו משתמשים?

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

לדוגמה:

כיף String.escapeForXml (): מחרוזת {....}

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

בתוך פונקציה זו, אנו יכולים לגשת למקלט באמצעות זֶה, כמו שכתבנו זאת בתוך ה- חוּט הכיתה עצמה:

כיף String.escapeForXml (): מחרוזת {להחזיר את .replace זה ("&", "&") .replace ("<", "", ">")}

3.1. כתיבת שיטות הרחבה כלליות

מה אם נרצה לכתוב שיטת הרחבה שנועדה להיות מיושמת על מספר סוגים, באופן כללי? אנחנו יכולים פשוט להאריך את כל סוג, - שהוא המקבילה ל- לְהִתְנַגֵד בכיתה בג'אווה - אבל יש דרך טובה יותר.

ניתן להחיל שיטות הרחבה על מקלט גנרי וגם על קונקרטי:

כיף T.concatAsString (b: T): מחרוזת {להחזיר this.toString () + b.toString ()}

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

לדוגמה, באמצעות הדוגמה שלעיל:

5.concatAsString (10) // מהדר "5" .concatAsString ("10") // מהדר 5.concatAsString ("10") // לא מהדר

3.2. כתיבת שיטות הרחבת אינפיקס

שיטות Infix שימושיות לכתיבת קוד בסגנון DSL, מכיוון שהן מאפשרות להתקשר לשיטות ללא המחזור או הסוגריים:

infix fun Number.toPowerOf (exponent: Number): כפול {return Math.pow (this.toDouble (), exponent.toDouble ())}

כעת אנו יכולים לקרוא לזה כמו לכל שיטת אינפיקס אחרת:

3 toPowerOf 2 // 9 9 toPowerOf 0.5 // 3

3.3. שיטות הרחבת מפעיל

נוכל גם לכתוב שיטת אופרטור כהרחבה.

שיטות המפעיל הן כאלו שמאפשרות לנו לנצל את קיצור המפעיל במקום שם השיטה המלא - למשל ועוד ניתן לקרוא לשיטת המפעיל באמצעות + מַפעִיל:

Fun fun List.times (מאת: Int): List {return this.map {it * by}}

שוב, זה עובד זהה לכל שיטת מפעיל אחרת:

listOf (1, 2, 3) * 4 // [4, 8, 12]

4. קריאה לפונקציה של הרחבה Kotlin מג'אווה

בואו נראה כעת כיצד ג'אווה פועלת עם פונקציות סיומת Kotlin.

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

עם זאת, איננו יכולים לקרוא לחלק משיטות ספריית Kotlin הרגילות ב- Java, כמו לתת אוֹ להגיש מועמדותכי הם מסומנים ב @InlineOnly.

4.1. נראות פונקציית ההרחבה המותאמת אישית ב- Java

בואו נשתמש באחת מפונקציות ההרחבה שהוגדרו קודם לכן - String.escapeXml (). הקובץ שלנו המכיל את שיטת ההרחבה נקרא StringUtil.kt.

כעת, כאשר אנו צריכים לקרוא לשיטת הרחבה מג'אווה, עלינו להשתמש בשם כיתה StringUtilKt. שימו לב שעלינו להוסיף את Kt סִיוֹמֶת:

מחרוזת xml = "היי"; מחרוזת escapedXml = StringUtilKt.escapeForXml (xml); assertEquals ("היי", escapedXml);

אנא שימו לב לראשון escapeForXml פָּרָמֶטֶר. טיעון נוסף זה הוא סוג מקלט פונקציית הרחבה. קוטלין עם פונקציית הרחבה ברמה העליונה הוא טהור ג'אווה כיתה בשיטה סטטית. לכן זה צריך לעבור איכשהו על המקור חוּט.

וכמובן, בדיוק כמו ב ג'אווה, אנו יכולים להשתמש בייבוא ​​סטטי:

יבוא com.baeldung.kotlin.StringUtilKt. * סטטי;

4.2. קוראים לשיטת הרחבה מובנית של קוטלין

קוטלין עוזר לנו לכתוב קוד קל ומהיר יותר על ידי מתן פונקציות הרחבות מובנות רבות. לדוגמא, יש את חוּט.לְנַצֵל() שיטה, אשר ניתן לקרוא ישירות מ ג'אווה:

שם מחרוזת = "ג'ון"; מחרוזת באותיות רישיות = StringsKt.capitalize (שם); assertEquals ("ג'ון", שם באותיות רישיות);

למרות זאת, איננו יכולים לקרוא לשיטות סיומת המסומנות באמצעות @InlineOnly מ ג'אווה, לדוגמה:

כיף מוטבע טלט (בלוק: (T) -> R): R.

4.3. שינוי שם המחלקה הסטטית של Java

אנחנו כבר יודעים שא קוטלין פונקציית הרחבה היא סטטית ג'אווה שיטה. בואו ונשנה שם שנוצר ג'אווה כיתה עם ביאור @ file: JvmName (שם: מחרוזת).

יש להוסיף זאת בראש הקובץ:

@ file: JvmName ("Strings") package com.baeldung.kotlin fun String.escapeForXml (): String {return this .replace ("&", "&") .replace ("<", "", ">" )}

עכשיו, כשאנחנו רוצים לקרוא לשיטת הרחבה, אנחנו פשוט צריכים להוסיף את ה- מיתרים שם הכיתה:

Strings.escapeForXml (xml);

כמו כן, אנו עדיין יכולים להוסיף ייבוא ​​סטטי:

יבוא com.baeldung.kotlin.Strings סטטי. *;

5. סיכום

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

ראינו כאן כמה שיטות הרחבה שמוכנות לשימוש במערכת. בנוסף, בחנו אפשרויות שונות של שיטות הרחבה. כמה דוגמאות לפונקציונליות זו ניתן למצוא באתר GitHub.


$config[zx-auto] not found$config[zx-overlay] not found