English | 简体中文 | 繁體中文 | Русский язык | Français | Español | Português | Deutsch | 日本語 | 한국어 | Italiano | بالعربية

دليل Kotlin الأساسي

تحكم Kotlin في العملية

الوظائف في Kotlin

النصوص في Kotlin

Kotlin موجه الأشياء (OOP)

الواجهة (Interface) في Kotlin

في هذا المقال، ستتعلم عن واجهات وكيفية تنفيذ واجهات في Kotlin.

واجهات Kotlin تشبه واجهات Java 8. يمكن أن تحتوي على تعريفات لطرق تجريبية وإجراءات غير تجريبية. ولكن لا يمكن أن تحتوي على أي حالة.

بمعنى أن الواجهة قد تحتوي على ميزات، ولكن يجب أن تكون تجريبية أو يجب أن تقدم تنفيذ الوصول.

موصى به للقراءة: فئات Kotlin التجريبية

فئات Kotlin مشابهة لواجهات Kotlin، ولكن هناك فرق مهم. ليست الميزات في الفئات التجريبية يجب أن تكون تجريبية أو يجب أن تقدم تنفيذ الوصول.

كيف يمكن تعريف واجهة؟

كلمة المفتاح interface تستخدم في Kotlin لتحديد واجهة. على سبيل المثال،

interface MyInterface {
    var test: String //ميزة تجريبية
    fun foo() //مетод تجريبي
    fun hello() = "مرحبًا هناك" //مетод يحتوي على تنفيذ افتراضي
{}

في هذا،

  • أنشئ واجهة MyInterface.

  • لدي هذه الواجهة ميزة تجريبية test ومетод تجريبي foo().

  • لدي هذه الواجهة أيضًا طريقة غير تجريبية hello().

كيف يمكن تنفيذ واجهة؟

هذا كيف يمكن للفئات أو الأشياء تنفيذ واجهة الطريقة:

interface MyInterface {
    val test: Int //ميزة تجريبية
    fun foo(): String //مетод تجريبي (يعود نص)
    fun hello() { //مетод يحتوي على تنفيذ افتراضي
        // جسم (اختياري)
    {}
{}
class InterfaceImp : MyInterface {
    override val test: Int = 25
    override fun foo() = "Lol"
    //كود آخر
{}

في هذا، كلاس InterfaceImp يحقق واجهة MyInterface.

في هذا، يعيد هذا الكلاس الأعضاء التجريبية للواجهة (ميزة test ومетод foo()).

مثال: كيف يعمل واجهة؟

interface MyInterface {
    val test: Int
    fun foo(): String
    fun hello() {
        println("مرحبًا، صديقي!")
    {}
{}
class InterfaceImp : MyInterface {
    override val test: Int = 25
    override fun foo() = "Lol"
{}
fun main(args: Array<String>) {
    val obj = InterfaceImp()
    println("اختبار = ${obj.test}")
    print("دعوة hello():")
    obj.hello()
    print("الإتصال والطباعة foo(): ")
    println(obj.foo())
{}

عند تشغيل البرنامج، الناتج سيكون:

test = 25
الإتصال hello(): مرحبًا، صديقي!
الإتصال والطباعة foo(): Lol

كما ذكرنا سابقًا، يمكن للواجهات أيضًا أن تحتوي على ممتلكات توفر تنفيذ الوصول. على سبيل المثال،

interface MyInterface {
    //ممتلكات مرفقة بالتنفيذ
    val prop: Int
        get() = 23
{}
class InterfaceImp : MyInterface {
    //جسم الفئة
{}
fun main(args: Array<String>) {
    val obj = InterfaceImp()
    println(obj.prop)
{}

عند تشغيل البرنامج، الناتج سيكون:

23

في هذا السياق، prop ليس نظيفًا، ولكن هو صالح في الواجهة لأنه يقدم تنفيذ الوصول.

لكن لا يمكنك تنفيذ عمليات مشابهة لـ val prop:Int = 23 في واجهة.

تنفيذ عدة واجهات في فئة واحدة

Kotlin لا يسمح بالميراث المتعدد الحقيقي. ولكن يمكن تنفيذ عدة واجهات في فئة واحدة. على سبيل المثال،

interface A {
    fun callMe() {
        println("من واجهة A")
    {}
{}
interface B  {
    fun callMeToo() {
        println("من واجهة B")
    {}
{}
//تنفيذ الواجهتين A و B
class Child: A, B
fun main(args: Array<String>) {
    val obj = Child()
    obj.callMe()
    obj.callMeToo()
{}

عند تشغيل البرنامج، الناتج سيكون:

من واجهة A
من واجهة B

حل نزاع التعريف (الميراث المتعدد للواجهات)

افترض أن لديك اثنين من الواجهات (A و B) لها نفس الاسم من الطرق غير المجردة (افترض طريقة callMe()). قمت بتنفيذ هذه الواجهتين في فئة واحدة (افترض فئة C). الآن، إذا استخدمت كائن فئة C لتشغيل طريقة callMe()، فإن محول البرمجيات سيقوم بإطلاق خطأ. على سبيل المثال

interface A {
    fun callMe() {
        println("واجهة A")
    {}
{}
interface B  {
    fun callMe() {
        println("واجهة B")
    {}
{}
class Child: A, B 
fun main(args: Array<String>) {
    val obj = Child()
    obj.callMe()
{}

هذا هو الخطأ الذي تم إطلاقه:

Error:(14, 1) Kotlin: Class 'C' must override public open fun callMe(): Unit defined in A because it inherits multiple interface methods of it

لحل هذه المشكلة، يجب عليك تقديم تنفيذ خاص بك. كيفية القيام بذلك:

interface A {
    fun callMe() {
        println("واجهة A")
    {}
{}
interface B  {
    fun callMe() {
        println("واجهة B")
    {}
{}
class C: A, B {
    override fun callMe() {
        super<A>.callMe()
        super<B>.callMe()
    {}
{}
fun main(args: Array<String>) {
    val obj = C()
    obj.callMe()
{}

الآن، عند تشغيل البرنامج، الناتج سيكون:

واجهة A
واجهة B

هنا، في صفحة C، تم تقديم تنفيذ واضح للدالة callMe()

class C: A, B {
    override fun callMe() {
        super<A>.callMe()
        super<B>.callMe()
    {}
{}

يُطلق على super<A>.callMe() دالة callMe() في صفحة A. وبالمثل، يُطلق على super<B>.callMe() دالة callMe() في صفحة B.