---
title: "الـ Interface في Kotlin ومتى تستخدمونها"
description: "تسمح Kotlin بأن تحتوي الـ Interface على كود، أي أن الصنف (class) يستطيع تنفيذ Interface ويرث سلوكها."
canonical: https://oozou.com/ar/blog/interface-in-kotlin-and-when-to-use-it-10
locale: ar
date: 2018-07-05
author: "OOZOU Team"
---

# الـ Interface في Kotlin ومتى تستخدمونها

> تسمح Kotlin بأن تحتوي الـ Interface على كود، أي أن الصنف (class) يستطيع تنفيذ Interface ويرث سلوكها.

Published: 2018-07-05 · Author: OOZOU Team (Engineering) · 4 min read

بعد استخدام Kotlin في تطوير تطبيقات Android لفترة، أدركت مؤخرًا فائدة **الـ Interface في Kotlin.** ففي Java 6 لا يمكن استخدام الـ Interface إلا لوصف السلوكيات، دون تنفيذها.

ولحسن الحظ، تسمح Kotlin بأن تحتوي الـ Interface على كود، أي أن الصنف (class) يستطيع تنفيذ Interface ويرث سلوكها.

بدايةً، إذا كنتم قادمين من Java، فربما لديكم interface كهذه.

```kotlin
interface FlyingVehicle {
  fun startEngine()
}
```

لنجعل صنفَي Aeroplane وHelicopter ينفّذان الـ Interface بهذا الشكل.

```kotlin
class AeroPlane : FlyingVehicle {
  val engine: Engine = Engine()
  override fun startEngine() = engine.start()
}
```
```kotlin
class Helicopter : FlyingVehicle {
  val engine: Engine = Engine()
  override fun startEngine() = engine.start()
}
```

لا عيب فيهما، صحيح؟ لكن بما أن Kotlin تسمح بوضع كود داخل الـ Interface، يمكننا تعريف property ليُعاد تعريفها (override) وتنفيذ الدوال داخل الـ Interface هكذا

```kotlin
interface FlyingVehicle {
  val engine: Engine
  fun startEngine() = engine.start()
}
```

ثم يكفي أن نعيد تعريف الـ property في أصنافنا كما يلي.

```kotlin
class AeroPlane : FlyingVehicle {
  override val engine: Engine = Engine()
}
```
```kotlin
class Helicopter : FlyingVehicle {
  override val engine: Engine = Engine()
}
```

وعندما نريد تشغيل محرك الطائرة أو المروحية، يمكننا استدعاء الدالة مباشرة هكذا!

```kotlin
val aeroPlane = AeroPlane()
val helicopter = Helicopter()

aeroPlane.startEngine()
helicopter.startEngine()
```

قد تتساءلون كيف نستخدم هذا عمليًا (بما يتجاوز تشغيل محرك طائرة ومروحية).

سآخذ مثالًا مستمدًا من جزء من كتاب [Kotlin for Android Developer](https://antonioleiva.com/kotlin-android-developers-book/) للمؤلف Antonio Leiva، وهو كتاب ممتاز لكل مطوّر Android يريد البدء باستخدام Kotlin.

باختصار، سننشئ interface تساعدنا على

- تعيين عنوان الـ toolbar
- التعامل مع النقر على قائمة الإعدادات

```kotlin
interface SettingToolbarManager {
  val toolbar: Toolbar

  var toolbarTitle: String
    get() = toolbar.title.toString()
    set(value) {
      toolbar.title = value
    }

  fun setOnMenuClickListener(onSettingClicked: () -> Unit) {
    toolbar.inflateMenu(R.menu.menu_setting)
    toolbar.setOnMenuItemClickListener {
      when(it.itemId) {
        R.id.action_setting -> onSettingClicked()
        else -> {}
      }
    }
  }

}
```

ثم في **MainActivity** أو أي activity أخرى تحتاج إلى قائمة الإعدادات، يمكننا جعلها تنفّذ الـ interface.

```kotlin
class MainActivity : AppCompatActivity(), SettingToolbarManager {

  override val toolbar by lazy { findViewById<Toolbar>(R.id.toolbar) }

  override fun onCreate(savedInstanceState: Bundle?) {
    super.onCreate(savedInstanceState)
    setContentView(R.layout.main_activity)

    toolbarTitle = "My Main Activity"
    setOnMenuClickListener {
      //Do what you want here
    }
  }

}
```

كما ترون، تساعدنا الـ interface على فصل بعض الكود المشترك عن الـ activities، فيبدو الكود أنظف قليلًا. كما يمكننا إعادة استخدامها في أماكن متعددة، فلا نحتاج إلى كتابة الكود نفسه مرارًا وتكرارًا.
لكن الـ interface ليست دائمًا الخيار المناسب لتبسيط الكود. لننظر في المثال التالي.

لننشئ interface تبسّط عملية إنشاء Toast

```kotlin
interface ToastManager {
   val context: Context

   fun shortToast(message: String) {
       Toast.makeText(context, message, Toast.LENGTH_SHORT).show()
   }

   fun longToast(message: String) {
       Toast.makeText(context, message, Toast.LENGTH_LONG).show()
   }
}
```

قد تبدو الـ activity التي تنفّذ هذه الـ interface هكذا.

```kotlin
class ToastActivity : AppCompatActivity(), ToastManager {
   override val context = this

   override fun onCreate(savedInstanceState: Bundle?) {
      super.onCreate(savedInstanceState)
      shortToast("This is short toast")
   }

}
```

يبدو كل شيء سليمًا في المثال أعلاه، فـ ToastManager تؤدي عملها جيدًا. لكن في هذه الحالة لدينا حل أسهل: يمكننا استخدام **Kotlin Extension!!**

فبدلًا من إنشاء interface كما فعلنا، يمكننا كتابة extension functions.

```kotlin
fun Activity.shortToast(text: String) {
    Toast.makeText(this, text, Toast.LENGTH_SHORT).show()
}

fun Activity.longToast(text: String) {
    Toast.makeText(this, text, Toast.LENGTH_LONG).show()
}
```

وكما ترون في المثال أدناه، يمكننا الوصول إلى الدالة longToast دون تنفيذ **interface** أو إعادة تعريف **context**، لأن ToastActivity ترث من AppCompatActivity، وهي بدورها نسخة (instance) من Activity.

```kotlin
class ToastActivity : AppCompatActivity() {

   override fun onCreate(savedInstanceState: Bundle?) {
      super.onCreate(savedInstanceState)
      longToast("This is long toast")
   }

}
```

# نقاش وخلاصة

**Interface** أم **Extension**

في رأيي، إذا كانت الوظيفة التي تريدون تحقيقها مشتركة بين كل نسخ صنف معيّن، فالـ **Extension** هي الخيار الأنسب. أما إذا أردتم سلوكًا أكثر تخصيصًا، فالـ **Interface** أنسب، مثل SettingToolbarManager في المثال أعلاه.

هذا مجرد رأيي الشخصي، فأخبروني إن كنتم لا توافقون عليه. :)

وفي كل الأحوال، الـ **Interface** طريقة رائعة لتبسيط الكود وتجنب التكرار.

# المصادر

- [https://medium.com/@rameshprasad/supercharged-interfaces-in-kotlin-53c506c53612](https://medium.com/@rameshprasad/supercharged-interfaces-in-kotlin-53c506c53612)
- كتاب Kotlin for Android Developers للمؤلف [Antonio Leiva](https://medium.com/u/a199eb0fa9a0?source=post_page-----5d32caab19be----------------------)([https://antonioleiva.com/kotlin-android-developers-book/](https://antonioleiva.com/kotlin-android-developers-book/))
- [https://antonioleiva.com/interfaces-kotlin/](https://antonioleiva.com/interfaces-kotlin/)

---

Contact OOZOU: hello@oozou.com · +66 2544 0000 · https://oozou.com/ar/contact

More for AI agents: https://oozou.com/llms.txt · every page has a markdown twin at its URL plus ".md"
