این کد لبه بخشی از دوره Kotlin Bootcamp برای برنامه نویسان است. اگر به ترتیب روی کدها کار کنید، بیشترین ارزش را از این دوره خواهید گرفت. بسته به دانش خود، ممکن است بتوانید برخی از بخش ها را مرور کنید. این دوره مختص برنامه نویسانی است که یک زبان شی گرا را می دانند و می خواهند Kotlin را یاد بگیرند.
مقدمه
در این کد لبه، شما یک برنامه Kotlin ایجاد می کنید و با کلاس ها و اشیاء در Kotlin آشنا می شوید. اگر زبان شی گرا دیگری بلد باشید، بیشتر این محتوا برای شما آشنا خواهد بود، اما کاتلین تفاوت های مهمی برای کاهش مقدار کد مورد نیاز برای نوشتن دارد. شما همچنین در مورد کلاس های انتزاعی و تفویض رابط کاربری یاد می گیرید.
به جای ساختن یک برنامه نمونه واحد، درسهای این دوره برای ایجاد دانش شما طراحی شدهاند، اما نیمه مستقل از یکدیگر باشند تا بتوانید بخشهایی را که با آنها آشنا هستید، مرور کنید. برای گره زدن آنها به یکدیگر، بسیاری از نمونه ها از تم آکواریوم استفاده می کنند. و اگر می خواهید داستان کامل آکواریوم را ببینید، دوره Kotlin Bootcamp for Programmers Udacity را بررسی کنید.
آنچه از قبل باید بدانید
- اصول اولیه کاتلین، از جمله انواع، عملگرها و حلقه زدن
- نحو تابع کاتلین
- اصول برنامه نویسی شی گرا
- اصول اولیه یک IDE مانند IntelliJ IDEA یا Android Studio
چیزی که یاد خواهید گرفت
- نحوه ایجاد کلاس ها و دسترسی به خصوصیات در Kotlin
- نحوه ایجاد و استفاده از سازنده کلاس در Kotlin
- نحوه ایجاد یک کلاس فرعی و نحوه عملکرد وراثت
- درباره کلاسهای انتزاعی، رابطها، و تفویض رابط
- نحوه ایجاد و استفاده از کلاس های داده
- نحوه استفاده از کلاس های سینگل، enum و مهر و موم شده
کاری که خواهی کرد
- یک کلاس با خصوصیات ایجاد کنید
- یک سازنده برای یک کلاس ایجاد کنید
- یک زیر کلاس ایجاد کنید
- نمونه هایی از کلاس ها و رابط های انتزاعی را بررسی کنید
- یک کلاس داده ساده ایجاد کنید
- در مورد تکتنها، enums و کلاسهای مهر و موم شده بیاموزید
اصطلاحات برنامه نویسی زیر باید قبلاً برای شما آشنا باشد:
- کلاس ها نقشه هایی برای اشیا هستند. به عنوان مثال، کلاس
Aquarium
طرح اولیه ساخت یک شی آکواریوم است. - اشیاء نمونه هایی از کلاس ها هستند. یک شی آکواریوم یک
Aquarium
واقعی است. - ویژگی ها ویژگی های طبقات هستند، مانند طول، عرض و ارتفاع یک
Aquarium
. - متدها که توابع عضو نیز نامیده می شوند، عملکرد کلاس هستند. روشها کارهایی هستند که میتوانید با شی «انجام دهید». به عنوان مثال، می توانید یک شی
Aquarium
fillWithWater()
. - واسط مشخصاتی است که یک کلاس می تواند پیاده سازی کند. به عنوان مثال، تمیز کردن برای اشیاء غیر از آکواریوم رایج است و تمیز کردن عموماً به روش های مشابه برای اشیاء مختلف انجام می شود. بنابراین می توانید یک رابط به نام
Clean
داشته باشید که متدclean()
تعریف می کند. کلاسAquarium
می تواند رابطClean
را برای تمیز کردن آکواریوم با یک اسفنج نرم پیاده سازی کند. - بسته ها راهی برای گروه بندی کدهای مرتبط به منظور سازماندهی نگه داشتن آن یا ایجاد کتابخانه ای از کدها هستند. پس از ایجاد یک بسته، می توانید محتویات بسته را به فایل دیگری وارد کنید و از کد و کلاس های موجود در آن مجددا استفاده کنید.
در این کار، یک بسته جدید و یک کلاس با برخی ویژگی ها و یک متد ایجاد می کنید.
مرحله 1: یک بسته ایجاد کنید
بسته ها می توانند به شما کمک کنند تا کد خود را سازماندهی کنید.
- در قسمت Project ، در زیر پروژه Hello Kotlin ، بر روی پوشه src راست کلیک کنید.
- New > Package را انتخاب کنید و آن را
example.myapp
بنامید.
مرحله 2: یک کلاس با ویژگی ها ایجاد کنید
کلاس ها با کلمه کلیدی class
تعریف می شوند و نام کلاس ها بر اساس قرارداد با یک حرف بزرگ شروع می شود.
- روی بسته example.myapp راست کلیک کنید.
- New > Kotlin File / Class را انتخاب کنید.
- در قسمت Kind ، Class را انتخاب کنید و نام کلاس را
Aquarium
بگذارید. IntelliJ IDEA نام بسته را در فایل گنجانده و یک کلاسAquarium
خالی برای شما ایجاد می کند. - در داخل کلاس
Aquarium
، ویژگی هایvar
را برای عرض، ارتفاع و طول (به سانتی متر) تعریف و مقداردهی اولیه کنید. خواص را با مقادیر پیش فرض مقداردهی کنید.
package example.myapp
class Aquarium {
var width: Int = 20
var height: Int = 40
var length: Int = 100
}
در زیر هود، کاتلین به طور خودکار گیرندهها و تنظیمکنندهها را برای ویژگیهایی که در کلاس Aquarium
تعریف کردهاید ایجاد میکند، بنابراین میتوانید مستقیماً به ویژگیها دسترسی داشته باشید، برای مثال myAquarium.length
.
مرحله 3: یک تابع main() ایجاد کنید
یک فایل جدید به نام main.kt
ایجاد کنید تا تابع main()
را نگه دارید.
- در قسمت Project در سمت چپ، روی بسته example.myapp راست کلیک کنید.
- New > Kotlin File / Class را انتخاب کنید.
- در زیر منوی کشویی Kind ، انتخاب را به عنوان File نگه دارید و نام فایل را
main.kt
بگذارید. IntelliJ IDEA شامل نام بسته است، اما تعریف کلاس برای یک فایل را شامل نمی شود. - یک تابع
buildAquarium()
تعریف کنید و در داخل یک نمونه ازAquarium
ایجاد کنید. برای ایجاد یک نمونه، کلاس را طوری ارجاع دهید که گویی یک تابع است،Aquarium()
. این سازنده کلاس را فراخوانی می کند و نمونه ای از کلاسAquarium
ایجاد می کند، مشابه استفاده ازnew
در زبان های دیگر. - یک تابع
main()
تعریف کنید وbuildAquarium()
را فراخوانی کنید.
package example.myapp
fun buildAquarium() {
val myAquarium = Aquarium()
}
fun main() {
buildAquarium()
}
مرحله 4: یک روش اضافه کنید
- در کلاس
Aquarium
، روشی برای چاپ مشخصات ابعاد آکواریوم اضافه کنید.
fun printSize() {
println("Width: $width cm " +
"Length: $length cm " +
"Height: $height cm ")
}
- در
main.kt
، درbuildAquarium()
، متدprintSize()
درmyAquarium
فراخوانی کنید.
fun buildAquarium() {
val myAquarium = Aquarium()
myAquarium.printSize()
}
- برنامه خود را با کلیک بر روی مثلث سبز رنگ کنار تابع
main()
اجرا کنید. نتیجه را رعایت کنید.
⇒ Width: 20 cm Length: 100 cm Height: 40 cm
- در
buildAquarium()
کدی را اضافه کنید تا ارتفاع را روی 60 تنظیم کنید و مشخصات ابعاد تغییر یافته را چاپ کنید.
fun buildAquarium() {
val myAquarium = Aquarium()
myAquarium.printSize()
myAquarium.height = 60
myAquarium.printSize()
}
- برنامه خود را اجرا کنید و خروجی را مشاهده کنید.
⇒ Width: 20 cm Length: 100 cm Height: 40 cm Width: 20 cm Length: 100 cm Height: 60 cm
در این کار، یک سازنده برای کلاس ایجاد میکنید و کار را با ویژگیها ادامه میدهید.
مرحله 1: یک سازنده ایجاد کنید
در این مرحله یک سازنده به کلاس Aquarium
که در اولین وظیفه ایجاد کردید اضافه می کنید. در مثال قبلی، هر نمونه از Aquarium
با همان ابعاد ساخته شده است. شما میتوانید بعد از ایجاد آن با تنظیم ویژگیها، ابعاد را تغییر دهید، اما سادهتر است که برای شروع اندازه آن را درست کنید.
در برخی از زبان های برنامه نویسی، سازنده با ایجاد متدی در کلاس که همان نام کلاس را دارد، تعریف می شود. در Kotlin، سازنده را مستقیماً در خود اعلان کلاس تعریف میکنید و پارامترهای داخل پرانتز را طوری مشخص میکنید که گویی کلاس یک متد است. مانند توابع در Kotlin، این پارامترها می توانند مقادیر پیش فرض را شامل شوند.
- در کلاس
Aquarium
که قبلا ایجاد کردید، تعریف کلاس را طوری تغییر دهید که شامل سه پارامتر سازنده با مقادیر پیشفرضlength
،width
وheight
باشد و آنها را به ویژگیهای مربوطه اختصاص دهید.
class Aquarium(length: Int = 100, width: Int = 20, height: Int = 40) {
// Dimensions in cm
var length: Int = length
var width: Int = width
var height: Int = height
...
}
- روش فشردهتر Kotlin این است که ویژگیها را مستقیماً با سازنده، با استفاده از
var
یاval
تعریف کنیم، و Kotlin همچنین گیرندهها و تنظیمکنندهها را بهطور خودکار ایجاد میکند. سپس می توانید تعاریف ویژگی را در بدنه کلاس حذف کنید.
class Aquarium(var length: Int = 100, var width: Int = 20, var height: Int = 40) {
...
}
- هنگامی که یک شی
Aquarium
با آن سازنده ایجاد می کنید، می توانید هیچ آرگومانی را مشخص نکنید و مقادیر پیش فرض را دریافت کنید، یا فقط تعدادی از آنها را مشخص کنید، یا همه آنها را مشخص کنید و یکAquarium
کاملاً سفارشی ایجاد کنید. در تابعbuildAquarium()
، راه های مختلف ایجاد یک شیAquarium
را با استفاده از پارامترهای نامگذاری شده امتحان کنید.
fun buildAquarium() {
val aquarium1 = Aquarium()
aquarium1.printSize()
// default height and length
val aquarium2 = Aquarium(width = 25)
aquarium2.printSize()
// default width
val aquarium3 = Aquarium(height = 35, length = 110)
aquarium3.printSize()
// everything custom
val aquarium4 = Aquarium(width = 25, height = 35, length = 110)
aquarium4.printSize()
}
- برنامه را اجرا کنید و خروجی را مشاهده کنید.
⇒ Width: 20 cm Length: 100 cm Height: 40 cm Width: 25 cm Length: 100 cm Height: 40 cm Width: 20 cm Length: 110 cm Height: 35 cm Width: 25 cm Length: 110 cm Height: 35 cm
توجه داشته باشید که لازم نیست سازنده را بیش از حد بارگذاری کنید و برای هر یک از این موارد نسخه متفاوتی بنویسید (به علاوه چند نسخه دیگر برای ترکیب های دیگر). Kotlin آنچه را که از مقادیر پیشفرض و پارامترهای نامگذاری شده لازم است ایجاد میکند.
مرحله 2: بلوک های init را اضافه کنید
سازنده های مثال بالا فقط ویژگی ها را اعلام می کنند و مقدار یک عبارت را به آنها اختصاص می دهند. اگر سازنده شما نیاز به کد اولیه بیشتری داشته باشد، می توان آن را در یک یا چند بلوک init
قرار داد. در این مرحله چند بلوک init
به کلاس Aquarium
اضافه می کنید.
- در کلاس
Aquarium
، یک بلوکinit
برای چاپی که شی در حال تنظیم اولیه است، و یک بلوک دوم برای چاپ حجم به لیتر اضافه کنید.
class Aquarium (var length: Int = 100, var width: Int = 20, var height: Int = 40) {
init {
println("aquarium initializing")
}
init {
// 1 liter = 1000 cm^3
println("Volume: ${width * length * height / 1000} l")
}
}
- برنامه را اجرا کنید و خروجی را مشاهده کنید.
aquarium initializing
Volume: 80 l
Width: 20 cm Length: 100 cm Height: 40 cm
aquarium initializing
Volume: 100 l
Width: 25 cm Length: 100 cm Height: 40 cm
aquarium initializing
Volume: 77 l
Width: 20 cm Length: 110 cm Height: 35 cm
aquarium initializing
Volume: 96 l
Width: 25 cm Length: 110 cm Height: 35 cm
توجه داشته باشید که بلوکهای init
به ترتیبی که در تعریف کلاس ظاهر میشوند اجرا میشوند و همه آنها با فراخوانی سازنده اجرا میشوند.
مرحله 3: درباره سازنده های ثانویه بیاموزید
در این مرحله با سازنده های ثانویه آشنا می شوید و یکی را به کلاس خود اضافه می کنید. علاوه بر یک سازنده اولیه، که می تواند یک یا چند بلوک init
داشته باشد، یک کلاس Kotlin می تواند یک یا چند سازنده ثانویه نیز داشته باشد تا امکان اضافه بار سازنده را فراهم کند، یعنی سازنده هایی با آرگومان های مختلف.
- در کلاس
Aquarium
یک سازنده ثانویه اضافه کنید که با استفاده از کلمه کلیدیconstructor
، تعدادی ماهی را به عنوان آرگومان خود در نظر بگیرد. یک خاصیتval
tank برای حجم محاسبه شده آکواریوم بر حسب لیتر بر اساس تعداد ماهی ایجاد کنید. فرض کنید 2 لیتر (2000 سانتی متر 3) آب به ازای هر ماهی، به علاوه کمی فضای اضافی تا آب نریزد.
constructor(numberOfFish: Int) : this() {
// 2,000 cm^3 per fish + extra room so water doesn't spill
val tank = numberOfFish * 2000 * 1.1
}
- در داخل سازنده ثانویه، طول و عرض (که در سازنده اولیه تنظیم شده است) را ثابت نگه دارید و ارتفاع مورد نیاز برای ایجاد حجم داده شده مخزن را محاسبه کنید.
// calculate the height needed
height = (tank / (length * width)).toInt()
- در تابع
buildAquarium()
یک فراخوان برای ایجاد یکAquarium
با استفاده از سازنده ثانویه جدید خود اضافه کنید. اندازه و حجم را چاپ کنید.
fun buildAquarium() {
val aquarium6 = Aquarium(numberOfFish = 29)
aquarium6.printSize()
println("Volume: ${aquarium6.width * aquarium6.length * aquarium6.height / 1000} l")
}
- برنامه خود را اجرا کنید و خروجی را مشاهده کنید.
⇒ aquarium initializing Volume: 80 l Width: 20 cm Length: 100 cm Height: 31 cm Volume: 62 l
توجه داشته باشید که حجم دو بار چاپ می شود، یک بار توسط بلوک init
در سازنده اولیه قبل از اجرای سازنده ثانویه، و یک بار توسط کد موجود در buildAquarium()
.
شما می توانستید کلمه کلیدی constructor
را نیز در سازنده اصلی قرار دهید، اما در بیشتر موارد ضروری نیست.
مرحله 4: یک گیرنده ویژگی جدید اضافه کنید
در این مرحله شما یک گیرنده خصوصیت واضح اضافه می کنید. کاتلین به طور خودکار دریافت کننده ها و تنظیم کننده ها را زمانی که ویژگی ها را تعریف می کنید تعریف می کند، اما گاهی اوقات مقدار یک ویژگی نیاز به تنظیم یا محاسبه دارد. به عنوان مثال، در بالا، حجم Aquarium
را چاپ کردید. شما می توانید حجم را به عنوان یک ویژگی با تعریف یک متغیر و یک گیرنده برای آن در دسترس قرار دهید. از آنجایی که volume
باید محاسبه شود، دریافت کننده باید مقدار محاسبه شده را برگرداند که می توانید با یک تابع یک خطی این کار را انجام دهید.
- در کلاس
Aquarium
یک ویژگیInt
به نامvolume
تعریف کنید و یک متدget()
تعریف کنید که حجم را در خط بعدی محاسبه می کند.
val volume: Int
get() = width * height * length / 1000 // 1000 cm^3 = 1 l
- بلوک
init
را که حجم را چاپ می کند بردارید. - کد موجود در
buildAquarium()
که حجم را چاپ می کند را حذف کنید. - در متد
printSize()
یک خط برای چاپ حجم اضافه کنید.
fun printSize() {
println("Width: $width cm " +
"Length: $length cm " +
"Height: $height cm "
)
// 1 l = 1000 cm^3
println("Volume: $volume l")
}
- برنامه خود را اجرا کنید و خروجی را مشاهده کنید.
⇒ aquarium initializing Width: 20 cm Length: 100 cm Height: 31 cm Volume: 62 l
ابعاد و حجم مانند قبل است، اما حجم فقط یک بار پس از مقداردهی اولیه شی توسط سازنده اولیه و سازنده ثانویه چاپ می شود.
مرحله 5: یک تنظیم کننده ویژگی اضافه کنید
در این مرحله یک تنظیم کننده ویژگی جدید برای حجم ایجاد می کنید.
- در کلاس
Aquarium
،volume
بهvar
تغییر دهید تا بتوان آن را بیش از یک بار تنظیم کرد. - با افزودن متد
set()
زیر گیرنده، که ارتفاع را بر اساس مقدار آب ارائه شده مجدداً محاسبه میکند، یک تنظیم کننده برای ویژگیvolume
اضافه کنید. طبق قرارداد، نام پارامتر تنظیم کنندهvalue
است، اما در صورت تمایل می توانید آن را تغییر دهید.
var volume: Int
get() = width * height * length / 1000
set(value) {
height = (value * 1000) / (width * length)
}
- در
buildAquarium()
کد اضافه کنید تا حجم آکواریوم را روی 70 لیتر تنظیم کنید. اندازه جدید را چاپ کنید.
fun buildAquarium() {
val aquarium6 = Aquarium(numberOfFish = 29)
aquarium6.printSize()
aquarium6.volume = 70
aquarium6.printSize()
}
- دوباره برنامه خود را اجرا کنید و ارتفاع و حجم تغییر یافته را مشاهده کنید.
⇒ aquarium initialized
Width: 20 cm Length: 100 cm Height: 31 cm
Volume: 62 l
Width: 20 cm Length: 100 cm Height: 35 cm
Volume: 70 l
تاکنون هیچ اصلاح کننده دید، مانند public
یا private
، در کد وجود نداشته است. به این دلیل که به طور پیشفرض، همه چیز در Kotlin عمومی است، به این معنی که همه چیز در همه جا قابل دسترسی است، از جمله کلاسها، متدها، ویژگیها و متغیرهای عضو.
در کاتلین، کلاسها، اشیاء، رابطها، سازندهها، توابع، ویژگیها و تنظیمکنندههای آنها میتوانند اصلاحکنندههای دید داشته باشند:
-
public
یعنی خارج از کلاس قابل مشاهده است. همه چیز به طور پیش فرض عمومی است، از جمله متغیرها و متدهای کلاس. -
internal
به این معنی است که فقط در آن ماژول قابل مشاهده خواهد بود. ماژول مجموعهای از فایلهای Kotlin است که با هم کامپایل شدهاند، برای مثال، یک کتابخانه یا برنامه. -
private
به این معنی است که فقط در آن کلاس (یا فایل منبع در صورتی که با توابع کار می کنید) قابل مشاهده است. -
protected
همانprivate
است، اما برای هر زیر کلاسی نیز قابل مشاهده خواهد بود.
برای اطلاعات بیشتر به Visibility Modifiers در مستندات Kotlin مراجعه کنید.
متغیرهای عضو
ویژگی های یک کلاس یا متغیرهای عضو به طور پیش فرض public
هستند. اگر آنها را با var
تعریف کنید، قابل تغییر هستند، یعنی قابل خواندن و نوشتن هستند. اگر آنها را با val
تعریف کنید، پس از مقداردهی اولیه فقط خواندنی هستند.
اگر خصوصیتی را میخواهید که کد شما بتواند بخواند یا بنویسد، اما کد خارجی فقط بتواند بخواند، میتوانید ویژگی و گیرنده آن را عمومی بگذارید و تنظیم کننده را خصوصی اعلام کنید، مانند شکل زیر.
var volume: Int
get() = width * height * length / 1000
private set(value) {
height = (value * 1000) / (width * length)
}
در این کار، یاد می گیرید که چگونه کلاس های فرعی و ارث بری در Kotlin کار می کنند. آنها شبیه به آنچه در زبان های دیگر دیده اید هستند، اما تفاوت هایی وجود دارد.
در کاتلین، به طور پیش فرض، کلاس ها را نمی توان زیر کلاسه کرد. به طور مشابه، ویژگیها و متغیرهای عضو نمیتوانند توسط زیر کلاسها لغو شوند (اگرچه میتوان به آنها دسترسی داشت).
شما باید یک کلاس را به عنوان open
علامت گذاری کنید تا اجازه دهید کلاس فرعی باشد. به طور مشابه، شما باید ویژگیها و متغیرهای عضو را بهعنوان open
علامتگذاری کنید تا آنها را در زیر کلاس لغو کنید. برای جلوگیری از لو رفتن تصادفی جزئیات پیاده سازی به عنوان بخشی از رابط کلاس، کلمه کلیدی open
مورد نیاز است.
مرحله 1: کلاس آکواریوم را باز کنید
در این مرحله کلاس Aquarium
را open
می کنید تا در مرحله بعد بتوانید آن را لغو کنید.
- کلاس
Aquarium
و تمام خصوصیات آن را با کلمه کلیدیopen
علامت گذاری کنید.
open class Aquarium (open var length: Int = 100, open var width: Int = 20, open var height: Int = 40) {
open var volume: Int
get() = width * height * length / 1000
set(value) {
height = (value * 1000) / (width * length)
}
- یک ویژگی
shape
باز با مقدار"rectangle"
اضافه کنید.
open val shape = "rectangle"
- یک خاصیت
water
آزاد را با یک گیرنده اضافه کنید که 90 درصد حجمAquarium
را برمی گرداند.
open var water: Double = 0.0
get() = volume * 0.9
- کد را به متد
printSize()
اضافه کنید تا شکل را چاپ کنید و مقدار آب را به صورت درصدی از حجم چاپ کنید.
fun printSize() {
println(shape)
println("Width: $width cm " +
"Length: $length cm " +
"Height: $height cm ")
// 1 l = 1000 cm^3
println("Volume: $volume l Water: $water l (${water/volume*100.0}% full)")
}
- در
buildAquarium()
کد را تغییر دهید تا یکAquarium
باwidth = 25
،length = 25
وheight = 40
ایجاد کنید.
fun buildAquarium() {
val aquarium6 = Aquarium(length = 25, width = 25, height = 40)
aquarium6.printSize()
}
- برنامه خود را اجرا کنید و خروجی جدید را مشاهده کنید.
⇒ aquarium initializing rectangle Width: 25 cm Length: 25 cm Height: 40 cm Volume: 25 l Water: 22.5 l (90.0% full)
مرحله 2: یک زیر کلاس ایجاد کنید
- یک زیر کلاس از
Aquarium
به نامTowerTank
ایجاد کنید که یک مخزن استوانه ای گرد را به جای مخزن مستطیلی اجرا می کند. میتوانیدTowerTank
زیرAquarium
اضافه کنید، زیرا میتوانید کلاس دیگری را در همان فایل کلاسAquarium
اضافه کنید. - در
TowerTank
، ویژگیheight
را که در سازنده تعریف شده است، لغو کنید. برای لغو یک ویژگی، از کلمه کلیدیoverride
در زیر کلاس استفاده کنید.
- سازنده
TowerTank
راdiameter
درآورید. هنگام فراخوانی سازنده در سوپرکلاسAquarium
diameter
هم برایlength
و همwidth
استفاده کنید.
class TowerTank (override var height: Int, var diameter: Int): Aquarium(height = height, width = diameter, length = diameter) {
- برای محاسبه یک استوانه، خاصیت حجم را نادیده بگیرید. فرمول یک استوانه پی ضربدر شعاع مجذور ارتفاع است. شما باید
PI
ثابت را ازjava.lang.Math
وارد کنید.
override var volume: Int
// ellipse area = π * r1 * r2
get() = (width/2 * length/2 * height / 1000 * PI).toInt()
set(value) {
height = ((value * 1000 / PI) / (width/2 * length/2)).toInt()
}
- در
TowerTank
، خاصیتwater
را 80 درصد حجم کنید.
override var water = volume * 0.8
-
shape
"cylinder"
را نادیده بگیرید.
override val shape = "cylinder"
- کلاس
TowerTank
نهایی شما باید چیزی شبیه به کد زیر باشد.
Aquarium.kt
:
package example.myapp
import java.lang.Math.PI
... // existing Aquarium class
class TowerTank (override var height: Int, var diameter: Int): Aquarium(height = height, width = diameter, length = diameter) {
override var volume: Int
// ellipse area = π * r1 * r2
get() = (width/2 * length/2 * height / 1000 * PI).toInt()
set(value) {
height = ((value * 1000 / PI) / (width/2 * length/2)).toInt()
}
override var water = volume * 0.8
override val shape = "cylinder"
}
- در
buildAquarium()
یکTowerTank
با قطر 25 سانتی متر و ارتفاع 45 سانتی متر ایجاد کنید. اندازه را چاپ کنید.
main.kt:
package example.myapp
fun buildAquarium() {
val myAquarium = Aquarium(width = 25, length = 25, height = 40)
myAquarium.printSize()
val myTower = TowerTank(diameter = 25, height = 40)
myTower.printSize()
}
- برنامه خود را اجرا کنید و خروجی را مشاهده کنید.
⇒ aquarium initializing rectangle Width: 25 cm Length: 25 cm Height: 40 cm Volume: 25 l Water: 22.5 l (90.0% full) aquarium initializing cylinder Width: 25 cm Length: 25 cm Height: 40 cm Volume: 18 l Water: 14.4 l (80.0% full)
گاهی اوقات می خواهید رفتار یا ویژگی های مشترکی را برای به اشتراک گذاشتن بین برخی کلاس های مرتبط تعریف کنید. Kotlin دو راه برای انجام این کار ارائه می دهد، رابط ها و کلاس های انتزاعی. در این کار، شما یک کلاس AquariumFish
انتزاعی برای خواصی که برای همه ماهی ها مشترک است ایجاد می کنید. شما یک رابط به نام FishAction
ایجاد می کنید تا رفتار مشترک همه ماهی ها را تعریف کنید.
- نه یک کلاس انتزاعی و نه یک رابط را نمی توان به تنهایی نمونه سازی کرد، به این معنی که شما نمی توانید اشیایی از آن نوع را مستقیما ایجاد کنید.
- کلاس های انتزاعی سازنده دارند.
- اینترفیس ها نمی توانند هیچ منطق سازنده ای داشته باشند یا هیچ حالتی را ذخیره کنند.
مرحله 1. یک کلاس انتزاعی ایجاد کنید
- در قسمت example.myapp ، یک فایل جدید به نام
AquariumFish.kt
ایجاد کنید. - یک کلاس ایجاد کنید که به آن
AquariumFish
نیز میگویند و آن را باabstract
علامتگذاری کنید. - یک ویژگی
String
،color
اضافه کنید و آن را باabstract
علامت بزنید.
package example.myapp
abstract class AquariumFish {
abstract val color: String
}
- دو زیر کلاس
AquariumFish
،Shark
وPlecostomus
ایجاد کنید. - از آنجایی که
color
انتزاعی است، زیر کلاس ها باید آن را پیاده سازی کنند.Shark
خاکستری وPlecostomus
را طلایی کنید.
class Shark: AquariumFish() {
override val color = "gray"
}
class Plecostomus: AquariumFish() {
override val color = "gold"
}
- در main.kt ، یک تابع
makeFish()
برای تست کلاس های خود ایجاد کنید. یکShark
و یکPlecostomus
را نمونه برداری کنید، سپس رنگ هر کدام را چاپ کنید. - کد تست قبلی خود را در
main()
حذف کنید و یک فراخوانی بهmakeFish()
اضافه کنید. کد شما باید چیزی شبیه به کد زیر باشد.
main.kt
:
package example.myapp
fun makeFish() {
val shark = Shark()
val pleco = Plecostomus()
println("Shark: ${shark.color}")
println("Plecostomus: ${pleco.color}")
}
fun main () {
makeFish()
}
- برنامه خود را اجرا کنید و خروجی را مشاهده کنید.
⇒ Shark: gray Plecostomus: gold
نمودار زیر نشان دهنده کلاس Shark
و کلاس Plecostomus
است که زیر کلاس کلاس انتزاعی، AquariumFish
.
مرحله 2. یک رابط ایجاد کنید
- در AquariumFish.kt ، یک رابط به نام
FishAction
با متدeat()
ایجاد کنید.
interface FishAction {
fun eat()
}
-
FishAction
به هر یک از زیر کلاسها اضافه کنید وeat()
را با چاپ کاری که ماهی انجام میدهد، پیادهسازی کنید.
class Shark: AquariumFish(), FishAction {
override val color = "gray"
override fun eat() {
println("hunt and eat fish")
}
}
class Plecostomus: AquariumFish(), FishAction {
override val color = "gold"
override fun eat() {
println("eat algae")
}
}
- در تابع
makeFish()
از هر ماهی که ایجاد کردید با فراخوانیeat()
چیزی بخورد.
fun makeFish() {
val shark = Shark()
val pleco = Plecostomus()
println("Shark: ${shark.color}")
shark.eat()
println("Plecostomus: ${pleco.color}")
pleco.eat()
}
- برنامه خود را اجرا کنید و خروجی را مشاهده کنید.
⇒ Shark: gray hunt and eat fish Plecostomus: gold eat algae
نمودار زیر نشان دهنده کلاس Shark
و کلاس Plecostomus
است که هر دو از رابط FishAction
تشکیل شده و پیاده سازی شده اند.
زمان استفاده از کلاس های انتزاعی در مقابل رابط ها
مثالهای بالا ساده هستند، اما وقتی کلاسهای مرتبط زیادی دارید، کلاسهای انتزاعی و رابطها میتوانند به شما کمک کنند طراحی خود را تمیزتر، سازماندهیتر و نگهداری راحتتر داشته باشید.
همانطور که در بالا ذکر شد، کلاس های انتزاعی می توانند سازنده داشته باشند، و رابط ها نمی توانند، اما در غیر این صورت بسیار شبیه هستند. بنابراین، چه زمانی باید از هر کدام استفاده کنید؟
هنگامی که از واسط ها برای نوشتن یک کلاس استفاده می کنید، عملکرد کلاس از طریق نمونه های کلاسی که در آن وجود دارد، گسترش می یابد. ترکیب تمایل دارد استفاده مجدد و استدلال کد را آسان تر از ارث بری از یک کلاس انتزاعی کند. همچنین، میتوانید از چندین رابط در یک کلاس استفاده کنید، اما فقط میتوانید از یک کلاس انتزاعی زیر کلاسبندی کنید.
ترکیب اغلب منجر به کپسوله سازی بهتر، اتصال کمتر (وابستگی متقابل)، رابط های تمیزتر و کدهای قابل استفاده بیشتر می شود. به این دلایل، استفاده از ترکیب با رابط ها طراحی ارجح است. از سوی دیگر، به ارث بردن از یک طبقه انتزاعی تمایل دارد برای برخی از مشکلات مناسب باشد. بنابراین شما باید ترکیب را ترجیح دهید، اما زمانی که وراثت منطقی است، کاتلین به شما اجازه می دهد این کار را نیز انجام دهید!
- اگر روشهای زیادی دارید و یک یا دو پیادهسازی پیشفرض دارید، برای مثال مانند
AquariumAction
زیر، از یک رابط استفاده کنید.
interface AquariumAction {
fun eat()
fun jump()
fun clean()
fun catchFish()
fun swim() {
println("swim")
}
}
- هر زمان که نمی توانید کلاس را کامل کنید از یک کلاس انتزاعی استفاده کنید. برای مثال، با بازگشت به کلاس
AquariumFish
، میتوانید تمامAquariumFish
به پیادهسازیFishAction
بسازید، و یک پیادهسازی پیشفرض برایeat
ارائه دهید در حالی کهcolor
را انتزاعی میگذارید، زیرا واقعاً یک رنگ پیشفرض برای ماهی وجود ندارد.
interface FishAction {
fun eat()
}
abstract class AquariumFish: FishAction {
abstract val color: String
override fun eat() = println("yum")
}
کار قبلی کلاس های انتزاعی، رابط ها و ایده ترکیب بندی را معرفی کرد. تفویض رابط یک تکنیک پیشرفته است که در آن متدهای یک رابط توسط یک شی کمک کننده (یا نماینده) پیاده سازی می شوند که سپس توسط یک کلاس استفاده می شود. این تکنیک زمانی میتواند مفید باشد که از یک رابط در یک سری کلاسهای غیرمرتبط استفاده میکنید: عملکرد رابط مورد نیاز را به یک کلاس کمکی جداگانه اضافه میکنید و هر یک از کلاسها از نمونهای از کلاس کمکی برای پیادهسازی عملکرد استفاده میکنند.
در این کار، از تفویض رابط برای افزودن قابلیت به یک کلاس استفاده می کنید.
مرحله 1: ایجاد یک رابط جدید
- در AquariumFish.kt ، کلاس
AquariumFish
حذف کنید. به جای ارث بردن از کلاسAquariumFish
،Plecostomus
وShark
قرار است رابط هایی را هم برای اکشن ماهی و هم برای رنگ آنها پیاده سازی کنند. - یک رابط جدید به
FishColor
ایجاد کنید که رنگ را به عنوان یک رشته تعریف می کند.
interface FishColor {
val color: String
}
-
Plecostomus
برای پیاده سازی دو رابط،FishAction
وFishColor
تغییر دهید. بایدcolor
ازFishColor
نادیده بگیرید وeat()
را ازFishAction
.
class Plecostomus: FishAction, FishColor {
override val color = "gold"
override fun eat() {
println("eat algae")
}
}
- کلاس
Shark
خود را تغییر دهید تا به جای ارث بردن ازAquariumFish
، دو رابطFishAction
وFishColor
را نیز پیاده سازی کنید.
class Shark: FishAction, FishColor {
override val color = "gray"
override fun eat() {
println("hunt and eat fish")
}
}
- کد تمام شده شما باید چیزی شبیه به این باشد:
package example.myapp
interface FishAction {
fun eat()
}
interface FishColor {
val color: String
}
class Plecostomus: FishAction, FishColor {
override val color = "gold"
override fun eat() {
println("eat algae")
}
}
class Shark: FishAction, FishColor {
override val color = "gray"
override fun eat() {
println("hunt and eat fish")
}
}
مرحله 2: یک کلاس تک تن درست کنید
سپس، با ایجاد یک کلاس کمکی که FishColor
را پیادهسازی میکند، تنظیمات بخش delegation را پیادهسازی میکنید. شما یک کلاس پایه به نام GoldColor
ایجاد می کنید که FishColor
پیاده سازی می کند - تمام کاری که انجام می دهد این است که رنگ آن طلایی است.
ایجاد چندین نمونه از GoldColor
منطقی نیست، زیرا همه آنها دقیقاً یک کار را انجام می دهند. بنابراین Kotlin به شما اجازه می دهد کلاسی را اعلام کنید که در آن فقط می توانید یک نمونه از آن را با استفاده از object
کلمه کلیدی به جای class
ایجاد کنید. کاتلین آن یک نمونه را ایجاد می کند و آن نمونه با نام کلاس ارجاع داده می شود. سپس تمام اشیاء دیگر فقط می توانند از این یک نمونه استفاده کنند—هیچ راهی برای ساختن نمونه های دیگر از این کلاس وجود ندارد. اگر با الگوی سینگلتون آشنا هستید، این روشی است که تکتنهها را در کاتلین پیادهسازی میکنید.
- در AquariumFish.kt یک شی برای
GoldColor
ایجاد کنید. رنگ را نادیده بگیرید.
object GoldColor : FishColor {
override val color = "gold"
}
مرحله 3: اضافه کردن نمایندگی رابط برای FishColor
اکنون برای استفاده از نمایندگی رابط آماده هستید.
- در AquariumFish.kt ، رد
color
را ازPlecostomus
حذف کنید. - کلاس
Plecostomus
را تغییر دهید تا رنگ آن را ازGoldColor
دریافت کنید. این کار را با افزودنby GoldColor
به اعلان کلاس و ایجاد نمایندگی انجام می دهید. چیزی که می گوید این است که به جای پیاده سازیFishColor
از پیاده سازی ارائه شده توسطGoldColor
استفاده کنید. بنابراین هر بار که بهcolor
دسترسی پیدا می شود، بهGoldColor
واگذار می شود.
class Plecostomus: FishAction, FishColor by GoldColor {
override fun eat() {
println("eat algae")
}
}
با کلاس همانطور که هست، تمام پلکوها طلایی خواهند شد، اما این ماهی ها در واقع رنگ های زیادی دارند. شما می توانید با افزودن یک پارامتر سازنده برای رنگ با GoldColor
به عنوان رنگ پیش فرض برای Plecostomus
به این موضوع رسیدگی کنید.
- کلاس
Plecostomus
را تغییر دهید تا درfishColor
با سازنده آن یک پاس داده شود و پیش فرض آن را رویGoldColor
قرار دهید. تغییر نمایندگی ازby GoldColor
بهby fishColor
.
class Plecostomus(fishColor: FishColor = GoldColor): FishAction,
FishColor by fishColor {
override fun eat() {
println("eat algae")
}
}
مرحله 4: تفویض اختیار رابط را برای FishAction اضافه کنید
به همین ترتیب، میتوانید از تفویض رابط برای FishAction
استفاده کنید.
- در AquariumFish.kt یک کلاس
PrintingFishAction
بسازید کهFishAction
را پیادهسازی میکند، که یکString
،food
میگیرد، سپس آنچه را که ماهی میخورد چاپ میکند.
class PrintingFishAction(val food: String) : FishAction {
override fun eat() {
println(food)
}
}
- در کلاس
Plecostomus
، تابع overrideeat()
را حذف کنید، زیرا آن را با یک نمایندگی جایگزین میکنید. - در بیانیه
Plecostomus
،FishAction
بهPrintingFishAction
واگذار کنید، با عبور از"eat algae"
. - با تمام آن تفویض، هیچ کدی در بدنه کلاس
Plecostomus
وجود ندارد، بنابراین{}
را حذف کنید، زیرا همه موارد لغو توسط تفویض رابط مدیریت می شوند.
class Plecostomus (fishColor: FishColor = GoldColor):
FishAction by PrintingFishAction("eat algae"),
FishColor by fishColor
نمودار زیر کلاس های Shark
و Plecostomus
را نشان می دهد که هر دو از رابط های PrintingFishAction
و FishColor
تشکیل شده اند، اما پیاده سازی را به آنها محول می کنند.
تفویض رابط قدرتمند است، و به طور کلی باید نحوه استفاده از آن را هر زمان که ممکن است از یک کلاس انتزاعی در زبان دیگری استفاده کنید، در نظر بگیرید. این به شما امکان می دهد از ترکیب بندی برای وصل کردن رفتارها استفاده کنید، به جای اینکه به زیر کلاس های زیادی نیاز داشته باشید که هر کدام به روشی خاص تخصص دارند.
یک کلاس داده شبیه یک struct
در برخی از زبانهای دیگر است - این کلاس عمدتاً برای نگهداری برخی دادهها وجود دارد - اما یک شی کلاس داده همچنان یک شی است. اشیاء کلاس داده Kotlin دارای مزایای اضافی مانند ابزارهای کاربردی برای چاپ و کپی هستند. در این کار، یک کلاس داده ساده ایجاد میکنید و با پشتیبانی Kotlin برای کلاسهای داده آشنا میشوید.
مرحله 1: یک کلاس داده ایجاد کنید
- برای نگه داشتن کد جدید، یک
decor
بسته جدید را در زیر بسته example.myapp اضافه کنید. روی example.myapp در قسمت Project کلیک راست کرده و File > New > Package را انتخاب کنید. - در بسته، یک کلاس جدید به نام
Decoration
ایجاد کنید.
package example.myapp.decor
class Decoration {
}
- برای تبدیل
Decoration
به یک کلاس داده، پیشوند اعلان کلاس را با کلمه کلیدیdata
قرار دهید. - یک ویژگی
String
به نامrocks
اضافه کنید تا به کلاس مقداری داده بدهید.
data class Decoration(val rocks: String) {
}
- در فایل، خارج از کلاس، یک تابع
makeDecorations()
برای ایجاد و چاپ نمونه ای از یکDecoration
با"granite"
اضافه کنید.
fun makeDecorations() {
val decoration1 = Decoration("granite")
println(decoration1)
}
- یک تابع
main()
برای فراخوانیmakeDecorations()
اضافه کنید و برنامه خود را اجرا کنید. به خروجی معقولی که ایجاد می شود توجه کنید زیرا این یک کلاس داده است.
⇒ Decoration(rocks=granite)
- در
makeDecorations()
دو شیءDecoration
دیگر را که هر دو "تخته" هستند نمونه برداری کنید و آنها را چاپ کنید.
fun makeDecorations() {
val decoration1 = Decoration("granite")
println(decoration1)
val decoration2 = Decoration("slate")
println(decoration2)
val decoration3 = Decoration("slate")
println(decoration3)
}
- در
makeDecorations()
یک عبارت print اضافه کنید که نتیجه مقایسهdecoration1
باdecoration2
را چاپ می کند و مورد دوم را کهdecoration3
باdecoration2
مقایسه می کند. از متد ()quals که توسط کلاس های داده ارائه می شود استفاده کنید.
println (decoration1.equals(decoration2))
println (decoration3.equals(decoration2))
- کد خود را اجرا کنید
⇒ Decoration(rocks=granite) Decoration(rocks=slate) Decoration(rocks=slate) false true
مرحله 2. از تخریب استفاده کنید
برای دستیابی به ویژگی های یک شی داده و اختصاص دادن آنها به متغیرها، می توانید آنها را یکی یکی تخصیص دهید، مانند این.
val rock = decoration.rock
val wood = decoration.wood
val diver = decoration.diver
درعوض، میتوانید متغیرهایی را برای هر ویژگی یک متغیر بسازید و شی داده را به گروه متغیرها اختصاص دهید. کاتلین مقدار ویژگی را در هر متغیر قرار می دهد.
val (rock, wood, diver) = decoration
به این می گویند ساختارشکنی و کوتاه نویسی مفیدی است. تعداد متغیرها باید با تعداد ویژگی ها مطابقت داشته باشد و متغیرها به ترتیبی که در کلاس اعلان شده اند نسبت داده می شوند. در اینجا یک مثال کامل است که می توانید در Decoration.kt امتحان کنید.
// Here is a data class with 3 properties.
data class Decoration2(val rocks: String, val wood: String, val diver: String){
}
fun makeDecorations() {
val d5 = Decoration2("crystal", "wood", "diver")
println(d5)
// Assign all properties to variables.
val (rock, wood, diver) = d5
println(rock)
println(wood)
println(diver)
}
⇒ Decoration2(rocks=crystal, wood=wood, diver=diver) crystal wood diver
اگر به یک یا چند ویژگی نیاز ندارید، میتوانید با استفاده از _
به جای نام متغیر، همانطور که در کد زیر نشان داده شده است، آنها را نادیده بگیرید.
val (rock, _, diver) = d5
در این کار، با برخی از کلاس های هدف ویژه در کاتلین آشنا می شوید، از جمله موارد زیر:
- کلاس های تک تن
- Enums
- کلاس های مهر و موم شده
مرحله 1: کلاس های تک تن را به یاد بیاورید
مثال قبلی را با کلاس GoldColor
به یاد بیاورید.
object GoldColor : FishColor {
override val color = "gold"
}
از آنجایی که هر نمونه از GoldColor
همان کار را انجام می دهد، به جای اینکه به عنوان یک class
، آن را به عنوان یک تک تن درآورد، به عنوان یک object
اعلان می شود. فقط یک نمونه از آن می تواند وجود داشته باشد.
مرحله 2: یک enum ایجاد کنید
Kotlin همچنین از enums پشتیبانی میکند که به شما امکان میدهد چیزی را برشمارید و با نام آن را ارجاع دهید، دقیقاً مانند سایر زبانها. با قرار دادن پیشوند اعلان با کلمه کلیدی enum
یک enum را اعلام کنید. یک اعلان اولیه فقط به فهرستی از نام ها نیاز دارد، اما می توانید یک یا چند فیلد مرتبط با هر نام را نیز تعریف کنید.
- در Decoration.kt ، نمونه ای از enum را امتحان کنید.
enum class Color(val rgb: Int) {
RED(0xFF0000), GREEN(0x00FF00), BLUE(0x0000FF);
}
Enum ها کمی شبیه تک تون ها هستند - از هر مقدار در شمارش فقط یک و فقط یکی می تواند وجود داشته باشد. برای مثال، فقط میتواند یک Color.RED
، یک Color.GREEN
و یک Color.BLUE
وجود داشته باشد. در این مثال، مقادیر RGB به خاصیت rgb
اختصاص داده شده است تا اجزای رنگ را نشان دهد. همچنین می توانید مقدار ترتیبی یک enum را با استفاده از ویژگی ordinal
و نام آن را با استفاده از ویژگی name
بدست آورید.
- نمونه دیگری از enum را امتحان کنید.
enum class Direction(val degrees: Int) {
NORTH(0), SOUTH(180), EAST(90), WEST(270)
}
fun main() {
println(Direction.EAST.name)
println(Direction.EAST.ordinal)
println(Direction.EAST.degrees)
}
⇒ EAST 2 90
مرحله 3: یک کلاس مهر و موم شده ایجاد کنید
یک کلاس مهر و موم شده، کلاسی است که می تواند زیر کلاسه شود، اما فقط در داخل فایلی که در آن اعلام شده است. اگر بخواهید کلاس را در فایل دیگری زیر کلاس بندی کنید، با خطا مواجه می شوید.
از آنجایی که کلاس ها و زیر کلاس ها در یک فایل قرار دارند، کاتلین تمام زیر کلاس ها را به صورت ایستا می شناسد. یعنی در زمان کامپایل، کامپایلر تمام کلاس ها و زیر کلاس ها را می بیند و می داند که این همه آنهاست، بنابراین کامپایلر می تواند بررسی های اضافی را برای شما انجام دهد.
- در AquariumFish.kt ، نمونه ای از یک کلاس مهر و موم شده را امتحان کنید، با موضوع آبزیان.
sealed class Seal
class SeaLion : Seal()
class Walrus : Seal()
fun matchSeal(seal: Seal): String {
return when(seal) {
is Walrus -> "walrus"
is SeaLion -> "sea lion"
}
}
کلاس Seal
را نمی توان در فایل دیگری طبقه بندی کرد. اگر می خواهید انواع Seal
بیشتری اضافه کنید، باید آنها را در همان فایل اضافه کنید. این باعث می شود کلاس های مهر و موم شده راهی ایمن برای نشان دادن تعداد ثابتی از انواع باشند. به عنوان مثال، کلاس های مهر و موم شده برای بازگشت موفقیت یا خطا از یک API شبکه عالی هستند.
این درس زمینه های زیادی را پوشش داد. در حالی که بسیاری از آن باید با سایر زبان های برنامه نویسی شی گرا آشنا باشد، کاتلین برخی ویژگی ها را اضافه می کند تا کد را مختصر و خوانا نگه دارد.
کلاس ها و سازنده ها
- با استفاده از
class
یک کلاس در Kotlin تعریف کنید. - کاتلین به طور خودکار تنظیم کننده ها و دریافت کننده ها را برای ویژگی ها ایجاد می کند.
- سازنده اولیه را مستقیماً در تعریف کلاس تعریف کنید. به عنوان مثال:
class Aquarium(var length: Int = 100, var width: Int = 20, var height: Int = 40)
- اگر سازنده اصلی نیاز به کد اضافی دارد، آن را در یک یا چند بلوک
init
بنویسید. - یک کلاس می تواند یک یا چند سازنده ثانویه را با استفاده از
constructor
تعریف کند، اما سبک Kotlin به جای استفاده از یک تابع کارخانه است.
اصلاح کننده های دید و زیر کلاس ها
- همه کلاسها و توابع در Kotlin به طور پیشفرض
public
هستند، اما میتوانید از اصلاحکنندهها برای تغییر قابلیت مشاهده بهinternal
،private
یاprotected
استفاده کنید. - برای ایجاد یک زیر کلاس، کلاس والد باید
open
علامت گذاری شود. - برای نادیده گرفتن متدها و خصوصیات در یک زیر کلاس، متدها و خصوصیات باید در کلاس والد
open
علامت گذاری شوند. - یک کلاس مهر و موم شده را می توان فقط در همان فایلی که در آن تعریف شده است زیر کلاس قرار داد. با قرار دادن پیشوند اعلان با
sealed
یک کلاس مهر و موم شده بسازید.
کلاسهای داده، تکتونها و enums
- با قرار دادن پیشوند اعلان با
data
یک کلاس داده بسازید. - Destructuring خلاصه ای برای تخصیص ویژگی های یک شی
data
به متغیرهای جداگانه است. - با استفاده از
object
به جایclass
، یک کلاس singleton بسازید. - با استفاده از
enum class
یک enum تعریف کنید.
کلاس های انتزاعی، رابط ها و تفویض اختیار
- کلاس های انتزاعی و رابط ها دو راه برای به اشتراک گذاشتن رفتار مشترک بین کلاس ها هستند.
- یک کلاس انتزاعی خصوصیات و رفتار را تعریف می کند، اما پیاده سازی را به زیر کلاس ها واگذار می کند.
- یک رابط رفتار را تعریف می کند و ممکن است اجرای پیش فرض را برای برخی یا همه رفتارها ارائه دهد.
- هنگامی که از واسط ها برای نوشتن یک کلاس استفاده می کنید، عملکرد کلاس از طریق نمونه های کلاسی که در آن وجود دارد، گسترش می یابد.
- تفویض رابط از ترکیب استفاده می کند، اما پیاده سازی را به کلاس های رابط نیز واگذار می کند.
- Composition یک راه قدرتمند برای افزودن عملکرد به کلاس با استفاده از تفویض رابط است. به طور کلی ترکیب بندی ترجیح داده می شود، اما ارث بردن از یک کلاس انتزاعی برای برخی از مشکلات مناسب تر است.
مستندات کاتلین
اگر در مورد هر موضوعی در این دوره اطلاعات بیشتری می خواهید، یا اگر گیر کرده اید، https://kotlinlang.org بهترین نقطه شروع شما است.
- طبقات و ارث
- سازندگان
- توابع کارخانه
- خواص و زمینه ها
- اصلاح کننده های دید
- کلاس های انتزاعی
- رابط ها
- هیئت نمایندگی
- کلاس های داده
- برابری
- در حال تخریب
- اعلامیه های اشیاء
- کلاس های Enum
- کلاس های مهر و موم شده
- مدیریت خطاهای اختیاری با استفاده از کلاس های مهر و موم شده Kotlin
آموزش های کوتلین
وب سایت https://try.kotlinlang.org شامل آموزش های غنی به نام Kotlin Koans ، یک مترجم مبتنی بر وب و مجموعه کاملی از مستندات مرجع با مثال است.
دوره udacity
برای مشاهده دوره Udacity در این موضوع ، برای برنامه نویسان به Kotlin Bootcamp مراجعه کنید.
ایده IntelliJ
مستندات ایده IntelliJ را می توان در وب سایت JetBrains یافت.
این بخش، تکالیف احتمالی را برای دانشآموزانی که در این آزمایشگاه کد به عنوان بخشی از دورهای که توسط یک مربی هدایت میشود، کار میکنند، فهرست میکند. این وظیفه مربی است که موارد زیر را انجام دهد:
- در صورت نیاز تکالیف را تعیین کنید.
- نحوه ارسال تکالیف را با دانش آموزان در میان بگذارید.
- تکالیف را نمره دهید.
مربیان میتوانند از این پیشنهادات به اندازهای که میخواهند استفاده کنند، و باید با خیال راحت هر تکلیف دیگری را که فکر میکنند مناسب است، محول کنند.
اگر به تنهایی از طریق این کدها کار می کنید، از این تکالیف برای آزمایش دانش خود استفاده کنید.
به این س questions الات پاسخ دهید
سوال 1
کلاس ها یک روش خاص دارند که به عنوان یک طرح برای ایجاد اشیاء آن کلاس عمل می کند. این روش چیست؟
▢ سازنده
▢ یک فوری
▢ سازنده
▢ یک طرح
سوال 2
کدام یک از گفته های زیر در مورد رابط ها و کلاس های انتزاعی صحیح نیست؟
class کلاسهای انتزاعی می توانند سازنده داشته باشند.
▢ رابط ها نمی توانند سازنده داشته باشند.
▢ رابط ها و کلاس های انتزاعی می توانند مستقیماً فوراً باشند.
properties خصوصیات انتزاعی باید توسط زیر کلاسهای کلاس انتزاعی اجرا شود.
سوال 3
کدام یک از موارد زیر اصلاح کننده قابلیت دید Kotlin برای خواص ، روش ها و غیره نیست؟
▢ internal
▢ nosubclass
▢ protected
▢ private
سوال 4
این کلاس داده را در نظر بگیرید:
data class Fish(val name: String, val species:String, val colors:String)
کدام یک از موارد زیر برای ایجاد و تخریب یک شیء Fish
، کد معتبر نیست؟
▢ val (name1, species1, colors1) = Fish("Pat", "Plecostomus", "gold")
▢ val (name2, _, colors2) = Fish("Bitey", "shark", "gray")
▢ val (name3, species3, _) = Fish("Amy", "angelfish", "blue and black stripes")
▢ val (name4, species4, colors4) = Fish("Harry", "halibut")
سوال 5
بیایید بگوییم شما یک باغ وحش با حیوانات زیادی دارید که همه آنها باید از آنها مراقبت شوند. کدام یک از موارد زیر جزئی از اجرای مراقبت نیست؟
▢ interface
برای انواع مختلف غذاهایی که حیوانات می خورند.
class کلاس abstract Caretaker
که از آن می توانید انواع مختلفی از سرپرستان را ایجاد کنید.
▢ interface
دادن آب تمیز به حیوان.
class کلاس data
برای ورود در یک برنامه تغذیه.
به درس بعدی بروید:
برای مرور کلی از این دوره ، از جمله پیوندها به سایر Codelabs ، به "Kotlin Bootcamp برای برنامه نویسان: به دوره خوش آمدید" مراجعه کنید.