מדריך לממשקי קוטלין

1. סקירה כללית

במדריך זה, נדון כיצד להגדיר וליישם ממשקים בקוטלין.

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

2. ממשקים בקוטלין

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

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

2.1. הגדרת ממשקים

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

ממשק SimpleInterface

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

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

ממשק SimpleInterface {fun firstMethod (): String fun secondMethod (): String {return ("Hello, World!")}}

הוספנו שתי שיטות לממשק שהוגדרנו בעבר:

  • אחד מהם קרא firstMethod היא שיטה מופשטת
  • ואילו השני התקשר ל- secondMethod יש יישום ברירת מחדל.

בואו נמשיך להוסיף כמה מאפיינים לממשק שלנו עכשיו:

ממשק SimpleInterface {val firstProp: String val secondProp: String get () = "מאפיין שני" כיף firstMethod (): String fun secondMethod (): String {return ("שלום, מ:" + secondProp)}}

כאן הוספנו שני מאפיינים לממשק שלנו:

  • אחד מהם התקשר firstProp הוא מסוג String והוא מופשט
  • השנייה התקשרה secondProp הוא גם מהסוג מחרוזת אך הוא מגדיר יישום לאקסור שלו.

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

ממשק SimpleInterface {val firstProp: String = "נכס ראשון" // הצהרה לא חוקית}

2.2. יישום ממשקים

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

class SimpleClass: SimpleInterface {override val firstProp: String = "נכס ראשון" לעקוף כיף firstMethod (): String {return ("שלום, מ:" + firstProp)}}

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

בואו נעקוף את כל המאפיינים והפונקציות שהוגדרו בעבר בכיתה שלנו:

class SimpleClass: SimpleInterface {override val firstProp: String = "First Property" עקיפת val secondProp: String get () = "נכס שני, נשלל!" לעקוף כיף firstMethod (): מחרוזת {return ("שלום, מ:" + firstProp)} לעקוף כיף secondMethod (): מחרוזת {return ("שלום, מ:" + secondProp + firstProp)}}

כאן ביטלנו את הנכס secondProp והפונקציה secondFunction שהוגדרו בעבר בממשק ממשק פשוט.

2.3 יישום ממשקים באמצעות משלחת

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

אם נתחיל בממשק בסיסי ובמחלקה:

ממשק MyInterface {fun someMethod (): String} class MyClass (): MyInterface {override fun someMethod (): String {return ("Hello, World!")}}

עד כה, שום דבר חדש. אך כעת, אנו יכולים להגדיר מחלקה אחרת המיישמת MyInterface באמצעות משלחת:

class MyDerivedClass (myInterface: MyInterface): MyInterface על ידי myInterface

MyDerivedClass מצפה מנציג כטיעון שמיישם בפועל את הממשק MyInterface.

בואו נראה איך נוכל לקרוא לפונקציה של הממשק באמצעות נציג:

val myClass = MyClass () MyDerivedClass (myClass) .someMethod ()

הנה אנו מיישרים הכיתה שלי ושימש את זה כציר להתקשר לפונקציות של הממשק MyDerivedClass, שלמעשה מעולם לא יישמה פונקציות אלה ישירות.

3. ירושה מרובה

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

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

ל- Java 8 יש מנגנונים משלה לטיפול בבעיית היהלומים, כמו לכל שפה אחרת המאפשרת ירושה מרובה.

בואו נראה איך קוטלין מטפל בזה באמצעות ממשקים.

3.1. ירושה ממשקים מרובים

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

ממשק FirstInterface {fun someMethod (): String fun anotherMethod (): String {return ("Hello, from anotherMethod in FirstInterface")}} ממשק SecondInterface {fun someMethod (): String {return ("Hello, from someMethod in SecondInterface") } fun otherMethod (): מחרוזת {return ("שלום, מ- OtherMethod ב- SecondInterface")}}

שים לב שלשני הממשקים יש שיטות עם אותו חוזה.

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

class SomeClass: FirstInterface, SecondInterface {override fun someMethod (): String {return ("Hello, from someMethod in SomeClass")} override fun anotherMethod (): String {return ("Hello, from anotherMethod in SomeClass")}}

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

3.2. פתרון סכסוכים

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

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

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

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

3.3. פתרון בעיית היהלום

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

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

ממשק BaseInterface {fun someMethod (): String} ממשק FirstChildInterface: BaseInterface {לעקוף כיף someMethod (): String {return ("שלום, מ someMethod ב- FirstChildInterface")}} ממשק SecondChildInterface: BaseInterface {לעקוף fun someMethod (): String {return ("שלום, מ someMethod ב- SecondChildInterface")}} מחלקה ChildClass: FirstChildInterface, SecondChildInterface {לעקוף כיף someMethod (): מחרוזת {להחזיר super.someMethod ()}}

כאן הגדרנו BaseInterface שהצהיר על פונקציה מופשטת הנקראת someMethod. שני הממשקים FirstChildInterface ו SecondChildInterface יורש מ BaseInterface וליישם את הפונקציה someMethod.

עכשיו כשאנחנו מיישמים ChildClass יורש מ FirstChildInterface ו SecondChildInterface, עלינו לבטל את הפונקציה someMethod. למרות זאת, למרות שאנחנו חייבים לעקוף את השיטה, אנחנו עדיין יכולים פשוט להתקשר סוּפֶּר כפי ש אנחנו עושים כאן עם SecondChildInterface.

4. ממשקים בהשוואה לשיעורים מופשטים בקוטלין

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

4.1. ההבדלים בין ממשק לשיעור מופשט

לַחֲכוֹת! זה לא נשמע בדיוק כמו מה שממשק עושה?

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

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

4.2. מתי עלינו להשתמש במה?

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

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

5. השוואה עם ממשקי Java

עם השינויים בממשק Java ב- Java 8, הם התקרבו מאוד לממשקי קוטלין. אחד המאמרים הקודמים שלנו לוכד את התכונות החדשות שהוצגו ב- Java 8 כולל שינויים בממשק.

יש כיום הבדלים תחביריים בין ממשקי Java ו- Kotlin. הבדל אחד הבולט קשור למילת המפתח "לעקוף". בקוטלין, בעוד שמיישמים מאפיינים מופשטים או פונקציות שעוברות בירושה מממשק, חובה להכשיר אותם עם מילת המפתח "לעקוף". אין דרישה מפורשת כזו בג'אווה.

6. מסקנה

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

לבסוף דנו בממשקים בהשוואה לשיעורים מופשטים בקוטלין. דיברנו בקצרה גם על השוואה בין ממשק קוטלין לממשק Java.

כמו תמיד, הקוד לדוגמאות זמין ב- GitHub.


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