Interface در کاتلین – آموزش اینترفیس و پیاده سازی آن + کد


اینترفیس موجودیت مهمی در برنامهنویسی شیگرا است که میتواند شامل تعریف «متُدهای» (Method) انتزاعی و پیادهسازی متدهای غیرانتزاعی باشد. قابلیت استفاده از Interface در کاتلین امکانات بیشتری را در کار با کلاسها در اختیار برنامهنویس قرار میدهد که از جمله آنها پیادهسازی وراثت چندگانه است. در این نوشته ابتدا مفهوم اینترفیس در کاتلین به بیان ساده توضیح داده میشود و سپس برای درک بهتر این مفهوم کاربردی، تفاوت بین کلاس و Interface در کاتلین بیان شده است. در ادامه نیز به کمک مثالهایی نحوه پیادهسازی اینترفیس در کاتلین توضیح داده میشود. همچنین در این نوشتار به موارد مهمی همچون ويژگیهای اینترفیس، پیادهسازی چندگانه Interface در کاتلین و وراثت در اینترفیسها پرداخته شده است.
مفهوم Interface در کاتلین چیست؟
اینترفیسها انواع سفارشی ارائه شده توسط کاتلین هستند که امکان نمونهسازی مستقیم آنها وجود ندارد. در عوض، اینترفیسها شکلی از رفتار را تعریف میکنند که اجرا کننده باید از آنها پیروی کند. با کمک اینترفیسها میتوان آرایههایی داشت که از ماهیت «اشیا» (Object) داخل خود خبر ندارند. این آرایهها صرفاً میدانند که اشیا ذخیره شده چه کارهایی میتوانند انجام دهند.
دلیل استفاده از اینترفیس در کاتلین
اینترفیس در برنامهنویسی شیگرا، ساختاری است که کامپیوتر را وادار میکند تا خصوصیتهایی را به یک شی اختصاص دهد. برای نمونه تصور کنید یک کلاس به نام Cat برای ساختن موجودیت گربه و یک کلاس به نام Cow برای ساخت موجودیت گاو و کلاس دیگری به نام Dog برای ساختن موجودیت سگ وجود داشته باشد.
در کلاسهای بالا عمل صحبت کردن را در نظر بگیرید. برای پیادهسازی این فرآیند باید برای هر کدام کلاسی وجود داشته باشد اما به کمک اینترفیس میتوان یک متد با نام Speak برای هر سه موجودیت پیادهسازی کرد. به بیان ساده استفاده از اینترفیس در کاتلین باعث کاهش حجم کدنویسی و در نتیجه صرفهجویی در زمان میشود.

تفاوت کلاس و اینترفیس در کاتلین چیست؟
مفهوم Interface در کاتلین میتواند شامل «اعلان» (Declare) متدهای انتزاعی و پیادهسازی آنها باشد. اینترفیس در کاتلین امکان ذخیرهسازی وضعیت را ندارد و همین مورد باعث تمایز میان اینترفیس و کلاس انتزاعی (Abstract Class) شده است. اینترفیسها میتوانند ویژگیهایی نیز داشته باشند اما باید انتزاعی باشند یا امکان پیادهسازی دسترسی را فراهم کنند.
چگونه یک Interface در کاتلین ایجاد کنیم؟
پیادهسازی اینترفیس در کاتلین با کلمه کلیدی Interface آغاز میشود و به دنبال آن، نام اینترفیس مورد نظر قرار داده میشود. در ادامه نیز اعضای اینترفیس درون کروشه باز و بسته قرار میگیرند. ویژگی مهمی که در اینترفیسها وجود دارد این است که اعضا هیچ تعریفی از خود ندارند، این تعاریف توسط انواع منطبق (Conforming Types) ارائه میشود.
روش پیاده سازی اینترفیس در کاتلین
Interface در کاتلین را به کمک کلاس یا شی میتوان پیاده سازی کرد. در زمان پیادهسازی اینترفیس، نوع منطبق باید تعریف را برای همه اعضای آن ارائه دهد. برای پیادهسازی اینترفیس، نام نوع سفارشی با یک دو نقطه و سپس نام اینترفیس مورد نظر قرار داده میشود. در ادامه پیادهسازی سادهای از Interface در کاتلین آورده شده است.
1interface Vehicle() {
2fun start()
3fun stop()
4}
بعد از ایجاد اینترفیس در کاتلین برای پیادهسازی و استفاده از آن در کلاس به صورت زیر باید عمل کرد.
1class Car: Vehicle
مثالی برای نشان دادن پیاده سازی Interface در کاتلین
در ادامه مثالی برای نمایش نحوه پیاده سازی Interface در کاتلین ارائه شده است.
1interface Vehicle {
2 fun start()
3 fun stop()
4}
5
6class Car : Vehicle {
7 override fun start()
8 {
9 println("Car started")
10 }
11
12 override fun stop()
13 {
14 println("Car stopped")
15 }
16}
17
18fun main()
19{
20 val obj = Car()
21 obj.start()
22 obj.stop()
23}
در ادامه خروجی نمونهکد بالا آورده شده است:
Car started Car stopped
در برنامه فوق، اینترفیسVehicle دو متدstart() وstop() را اعلان میکند که باید بازنویسی شوند. کلاسCar اینترفیس را با استفاده از سینتکس (قواعد نحوی) کلاس پیادهسازی میکند و با کلمه کلیدیoverride دو متد مورد نظر را بازنویسی میشوند. در نهایت، تابعmain یک شی از کلاسCar ایجاد و دو متد مورد نظر را فراخوانی میکند.
اینترفیس در کاتلین با پیاده سازی پیش فرض
Interface در کاتلین میتواند پیادهسازیهای پیشفرض برای توابع داشته باشد. در کد زیر، اینترفیسMyInterface با پیادهسازی پیشفرض تابعwithImplementation همراه است.
1interface MyInterface {
2 fun withImplementation() {
3 print("withImplementation() was called")
4 }
5}
در نتیجه کلاسهایی که چنین اینترفیسهایی را پیادهسازی میکنند، این امکان را دارند تا از توابع موجود در Interface بدون پیاده سازی مجدد استفاده کنند.
1class MyClass: MyInterface {
2 // No need to reimplement here
3}
4 val instance = MyClass()
5 instance.withImplementation()
در کد فوق، کلاسMyClass بدون نیاز به پیادهسازی مجدد امکان استفاده از تابع پیشفرضwithImplementation را دارد.
معرفی فیلم های آموزش برنامه نویسی اندروید

زبان برنامهنویسی کاتلین (Kotlin Programming Language) در حال حاضر به عنوان یکی از محبوبترین زبانها در میان جامعه توسعهدهندگان نرمافزارهای کاربردی موبایل شناخته میشود. همچنین جامعه توسعهدهندگان آن به سرعت در حال افزایش است. در سال ۲۰۱۷ میلادی (1396 شمسی)، گوگل، کاتلین را به عنوان دومین زبان رسمی برای توسعه اندروید معرفی کرد. از آن زمان تاکنون، رشد بسیار بزرگ و مهمی در تقاضا برای این زبان برنامهنویسی در میان توسعهدهندگان و جوامع کسب و کار به وقوع پیوسته است. گوگل در حال حاضر زبان برنامه نویسی کاتلین را به عنوان یکی از بهترین زبانهای برنامهنویسی برای توسعه اپلیکیشنهای اندرویدی اعلام کرده است. این نشان میدهد که آینده خوبی در انتظار این زبان برنامهنویسی است.
در پلتفرم فرادرس، دورههای آموزشی مرتبط با زبان برنامه نویسی کاتلین در مجموعه آموزشهای اندروید قابل دسترسی هستند. دورههای آموزش زبان برنامهنویسی کاتلین در این مجموعه به صورت پروژهمحور و موضوعی قرار داده شدهاند. علاوه بر این، دورههایی نیز برای یادگیری برنامهنویسی اندروید در این مجموعه وجود دارد. در تصویر بالا تنها تعداد کمی از دورههای موجود در این مجموعه آموزشی بهعنوان نمونه آمدهاند.
- برای شروع یادگیری برنامهنویسی کاتلین و دسترسی به همه دورههای آموزش اندروید + اینجا کلیک کنید.
مقادیر و متدهای پیشفرض در اینترفیس کاتلین
متدها در اینترفیس میتوانند مقادیر پیشفرضی برای پارامترهای خود داشته باشند. اگر مقدار پارامتر در زمان فراخوانی تابع ارائه نشده باشد، از مقدار پیشفرض آن استفاده میشود. همچنین متدها نیز میتوانند پیادهسازیهای پیشفرض داشته باشند. از این حالت در مواردی استفاده میشود که متد بازنویسی نشده باشد.
مثالی از کاربرد مقادیر و متدهای پیشفرض در اینترفیس کاتلین
در ادامه مثالی برای نشان دادن مقادیر و متدهای پیشفرض آورده شده است.
1interface FirstInterface {
2 fun add(a: Int, b: Int = 5)
3 fun print()
4 {
5 println("This is a default method defined in the interface")
6 }
7}
8class InterfaceDemo : FirstInterface {
9 override fun add(a: Int, b: Int)
10 {
11 val x = a + b
12 println("Sum is $x")
13 }
14
15 override fun print()
16 {
17 super.print()
18 println("It has been overridden")
19 }
20}
21
22fun main()
23{
24 val obj = InterfaceDemo()
25 println(obj.add(5))
26 obj.print()
27}
خروجی نمونه کد بالا در زیر آورده شده است.
Sum is 10 This is a default method defined in the interface It has been overridden
در برنامه فوق، اینترفیسFirstInterface دو متدadd() وprint() را تعریف میکند. متدadd() دارای دو پارامتر است که یکی از آنها دارای مقدار پیشفرض 5 است. همچنین متدprint() نیز به صورت پیشفرض پیادهسازی شده است. بنابراین، وقتی کلاسInterfaceDemo اینترفیس را پیادهسازی میکند، هر دو متد را بازنویسی میکند و اجرای پیشفرضprint() را با کلمه کلیدیsuper فراخوانی میکند. همچنین در تابعmain در زمان فراخوانی متدadd() تنها یک آرگومان مشخص میشود، زیرا به آرگومان دوم یک مقدار پیشفرض داده شده است.
ویژگیهای اینترفیس در کاتلین کدامند؟
دقیقا همانند متدها، اینترفیسها نیز میتوانند دارای ویژگی (Attribute | Property) باشند. با این حال، از آنجا که اینترفیس حالتی ندارد، امکان نمونهسازی آنها وجود ندارد. بنابراین هیچ فیلدی برای نگهداری مقادیر آنها وجود ندارد. در نتیجه، فیلدهای اینترفیس یا انتزاعی هستند یا به صورت پیادهسازی ارائه میشوند.

مثالی برای کاربرد ویژگیهای Interface در کاتلین
در ادامه نمونه کدی برای تعیین ویژگیهای اینترفیس در کاتلین و نحوه بازنویسی و استفاده از آنها در کلاس آورده شده است.
1interface InterfaceProperties {
2 val a : Int
3 val b : String
4 get() = "Hello"
5}
6
7class PropertiesDemo : InterfaceProperties {
8 override val a : Int = 5000
9 override val b : String = "Property Overridden"
10}
11
12fun main()
13{
14 val x = PropertiesDemo()
15 println(x.a)
16 println(x.b)
17}
در ادامه خروجی نمونه کد بالا آورده شده است.
5000 Property Overridden
در برنامه فوق، اینترفیسInterfaceProperties داری دو ویژگی است. ويژگیa از نوع عدد صحیح است و ویژگیb از نوع رشته به صورت گیرنده ارائه میشود. کلاسPropertiesDemo که اینترفیسInterfaceProperties را پیادهسازی میکند، دو ویژگی مربوط به این اینترفیس را بازنویسی میکند و برای آنها مقدار جدیدی در نظر میگیرد. در انتها نیز تابعmain شیئی از کلاس را ایجاد میکند. شی ایجاد شده با استفاده از علامت نقطه در سینتکس این زبان به Property-های کلاس دسترسی پیدا میکند.
پیادهسازی چندگانه Interface در کاتلین
گاهی اوقات در برنامه چندین اینترفیس تابع مشابهی را پیادهسازی میکنند، یا همه آنها با هم یک یا چند پیادهسازی را تعریف میکنند. در نتیجه، این نحوه تعریف باعث خطا خواهد شد، به این خاطر که برای کامپایلر برنامه مبهم است که کدام پیادهسازی باید استفاده شود. کلاس مشتق شده باید به صورت دستی فراخوانی مناسب را ارائه دهد.
مثالی از پیادهسازی چندگانه Interface در کاتلین
در ادامه مثالی برای روشن شدن این موضوع آورده شده است.
1interface A {
2fun notImplemented()
3fun implementedOnlyInA() { print("only A") }
4fun implementedInBoth() { print("both, A") }
5fun implementedInOne() { print("implemented in A") }
6}
7
8interface B {
9fun implementedInBoth() { print("both, B") }
10// only defined
11fun implementedInOne()
12}
13
14class MyClass: A, B {
15override fun notImplemented() { print("Normal implementation") }
16// implementedOnlyInA() can by normally used in instances
17// class needs to define how to use interface functions
18override fun implementedInBoth() {
19super<B>.implementedInBoth()
20super<A>.implementedInBoth()
21}
22
23// even if there's only one implementation,
24// there multiple definitions
25override fun implementedInOne() {
26super<A>.implementedInOne()
27print("implementedInOne class implementation")
28}
29}
در کد بالا کلاسMyClass از دو اینترفیسA وB مشتق شده است. هر دو اینترفیس دارای تابع مشترکی با نامimplementedInBoth() با خروجی متفاوت هستند. بنابراین، کلاس در زمان استفاده از تابع موجود در هر کدام از اینترفیسها باید با کمک کلمه کلیدیsuper<A> یاsuper<B> به صورت واضح مشخص کند که از پیادهسازی موجود در کدام اینترفیس استفاده میکند.

وراثت در اینترفیس کاتلین
اینترفیسها در کاتلین میتوانند سایر اینترفیسها را نیز به ارث ببرند. زمانی که یک اینترفیس از اینترفیس دیگری ارثبری میکند، این امکان فراهم است تا ويژگیها و متدهای خود را اضافه کند. در بحث پیادهسازی نیز باید برای همه ويژگیها و متدها در هر دو اینترفیس تعریفی ارائه دهد. یک Interface در کاتلین میتواند بیش از یک اینترفیس را به ارث ببرد. در کد زیر مثالی برای نشان دادن وراثت در اینترفیس ارائه شده است.
1interface Dimensions {
2 val length : Double
3 val breadth : Double
4}
5
6interface CalculateParameters : Dimensions {
7 fun area()
8 fun perimeter()
9}
10
11class XYZ : CalculateParameters {
12 override val length : Double
13 get() = 10.0
14 override val breadth : Double
15 get()= 15.0
16
17 override fun area()
18 {
19 println("Area is ${length * breadth}")
20 }
21
22 override fun perimeter()
23 {
24 println("Perimeter is ${2*(length+breadth)}")
25 }
26}
27
28fun main()
29{
30 val obj = XYZ()
31 obj.area()
32 obj.perimeter()
33}
در ادامه نیز خروجی کد بالا آورده شده است.
Area is 150.0 Perimeter is 50.0
در برنامه فوق، اینترفیسDimensions دو ویژگی طول و عرض را تعریف میکند. اینترفیسCalculatedParameters اینترفیسDimensions را به ارث میبرد و همچنین دو متدarea() وperimeter() را اضافه میکند. کلاسXYZ نیز اینترفیسCalculatedParameters را پیادهسازی میکند و ویژگیها و متدهای آن را بازنویسی میکند که در نهایت در تابع اصلی برنامه فراخوانی میشوند.

وراثت چندگانه اینترفیس در کاتلین
کلاسها در کاتلین از مفهوم وراثت واحد پیروی میکنند، یعنی هر کلاس فقط میتواند کلاس را به ارث ببرد، اما در مورد اینترفیسها در کاتلین یک کلاس از «وراثت چندگانه» (Multiple Inheritance) پشتیبانی میکند که در زبان برنامه نویسی کاتلین به عنوان «انطباق چندگانه» (multiple conformance) نیز شناخته میشود. در مبحث Interface در کاتلین یک کلاس میتواند بیش از یک اینترفیس را پیادهسازی کند، مشروط بر اینکه تعریفی برای همه اعضای اینترفیس ارائه کند.
مثالی برای نشان دادن وراثت چندگانه اینترفیس در کاتلین
در این بخش از نوشته نمونه کدی برای تعیین نحوه پیادهسازی و کاربرد وراثت چندگانه در Interface در کاتلین آورده شده است.
1interface InterfaceProperties {
2 val a : Int
3 val b : String
4 get() = "Hello"
5}
6
7interface InterfaceMethods {
8 fun description()
9}
10
11class MultipleInterface : InterfaceProperties, InterfaceMethods {
12 override val a : Int
13 get() = 50
14
15 override fun description()
16 {
17 println("Multiple Interfaces implemented")
18 }
19}
20fun main()
21{
22 val obj = MultipleInterface()
23 obj.description()
24}
در ادامه نیز خروجی کد بالا نیز آورده شده است.
Multiple Interfaces implemented
در این برنامه دو اینترفیسInterfaceProperties وInterfaceMethods تعریف شدهاند. این اینترفیسها توسط کلاسMultipleInterface پیادهسازی شدهاند و سپس متدها در تابعmain فراخوانی میشوند.
کلمه کلیدی super در Interface
اگر متد موجود در اینترفیس پیادهسازی پیشفرض خود را داشته باشد، امکان استفاده از کلیدواژه super برای دسترسی به آن متد وجود دارد.
1interface MyInterface {
2 fun funcOne() {
3 // optional body
4 print("Function with default implementation")
5 }
6}
در نمونه کد بالا متدfuncOne() دارای پیادهسازی پیشفرض است؛ در نتیجه با استفاده از علامت نقطه در سینتکس این زبان امکان دسترسی به متد اینترفیس وجود دارد. در ادامه نحوه دسترسی به متد مورد نظر با استفاده از کلمه کلیدی super آورده شده است.
super.funcOne()
فواید استفاده از Interface
تا اینجا نکات خوبی در مورد مفهوم، کاربرد و نحوه پیادهسازی اینترفیس در کاتلین بیان شد. در ادامه به صورت مختصر مزایای استفاده از قابلیت Interface در کار با کلاسهای انتزاعی بررسی میشود. بهطور کلی Interfaceها دارای مزایای زیر هستند:
- با استفاده از اینترفیس کارها بیشتر به صورت انتزاعی انجام میشوند و این مورد باعث صرفهجویی در زمان توسعه برنامه خواهد شد.
- برنامهنویس این امکان را خواهد داشت که برای هر کلاسی که براساس یک Interface پیادهسازی میشود، توابع خاص را بنویسد.
- چندین کلاس که از منظر خصوصیات به هم نزدیک هستند را میتوان بر پایه یک Interface پیادهسازی کرد.
- یادگیری اینترفیس در کاتلین درک مفاهیم شیگرایی در این زبان را آسانتر میکند.
- قابلیت وراثت چندگانه در اینترفیسها وجود دارد، درحالی که این موضوع در کلاسهای انتزاعی وجود ندارد.
جمعبندی
در این نوشتار بهطور جامع پیرامون مبحث مهم و کاربردی اینترفیس در کاتلین بحث شد. بهطور کلی ساختار اینترفیس در کاتلین و «جاوا» (Java) مشابه است و تفاوت چندانی ندارد. مرز بین دو مفهوم کلاس و Interface بسیار نزدیک به یکدیگر است. در نتیجه، توانایی تشخیص دادن این دو مفهوم از یکدیگر و همچنین آشنا بودن به تفاوتها و کاربردهای هر کدام برای هر توسعهدهندهای که از زبان برنامهنویسی کاتلین استفاده میکند، بسیار ضروری است.
در این نوشته سعی شد تا مفهوم اینترفیس در کاتلین به سادگی بیان شود. همچنین با ارائه مثالهای متنوعی در زمینههای مختلف کار با Interface، از وراثت گرفته تا پیادهسازی های چندگانه سعی شد تا این مبحث مهم و کاربردی به سادگی درک شود.