این Codelab بخشی از دوره Kotlin Bootcamp برای برنامه نویسان است . اگر به ترتیب روی کدها کار کنید، بیشترین ارزش را از این دوره خواهید گرفت. بسته به دانش خود، ممکن است بتوانید برخی از بخش ها را مرور کنید. این دوره برای برنامه نویسانی است که زبان شی گرا را می دانند و می خواهند Kotlin را یاد بگیرند.
مقدمه
در این Codelab با کلاس ها، توابع و متدهای عمومی و نحوه کار آنها در Kotlin آشنا می شوید.
به جای ساختن یک برنامه نمونه واحد، درسهای این دوره برای ایجاد دانش شما طراحی شدهاند، اما نیمه مستقل از یکدیگر باشند تا بتوانید بخشهایی را که با آنها آشنا هستید، مرور کنید. برای گره زدن آنها به یکدیگر، بسیاری از نمونه ها از تم آکواریوم استفاده می کنند. و اگر می خواهید داستان کامل آکواریوم را ببینید، دوره Kotlin Bootcamp for Programmers Udacity را بررسی کنید.
آنچه از قبل باید بدانید
- نحو توابع، کلاس ها و متدهای کاتلین
- نحوه ایجاد یک کلاس جدید در IntelliJ IDEA و اجرای یک برنامه
چیزی که یاد خواهید گرفت
- نحوه کار با کلاس ها، متدها و توابع عمومی
کاری که خواهی کرد
- یک کلاس عمومی ایجاد کنید و محدودیت ها را اضافه کنید
- انواع
in
وout
ایجاد کنید - توابع، متدها و توابع توسعه عمومی را ایجاد کنید
مقدمه ای بر ژنریک
کاتلین مانند بسیاری از زبان های برنامه نویسی دارای انواع عمومی است. یک نوع عمومی به شما امکان می دهد یک کلاس را عمومی کنید و در نتیجه یک کلاس را بسیار انعطاف پذیرتر کنید.
تصور کنید در حال پیاده سازی یک کلاس MyList
که لیستی از آیتم ها را در خود جای داده است. بدون ژنریک، شما باید یک نسخه جدید از MyList
را برای هر نوع پیاده سازی کنید: یکی برای Double
، یکی برای String
، یکی برای Fish
. با ژنریک، می توانید لیست را عمومی کنید، بنابراین می توانید هر نوع شی را در خود جای دهید. مانند این است که تایپ را به صورت عام درآورید که برای انواع مختلف مناسب باشد.
برای تعریف یک نوع عمومی، T را در پرانتزهای زاویه <T>
بعد از نام کلاس قرار دهید. (می توانید از حرف دیگری یا نام طولانی تر استفاده کنید، اما قرارداد یک نوع عمومی T است.)
class MyList<T> {
fun get(pos: Int): T {
TODO("implement")
}
fun addItem(item: T) {}
}
شما می توانید T
را به عنوان یک نوع معمولی ارجاع دهید. نوع برگشتی get()
T
است و پارامتر addItem()
از نوع T
است. البته لیست های عمومی بسیار مفید هستند، بنابراین کلاس List
در Kotlin تعبیه شده است.
مرحله 1: یک سلسله مراتب نوع ایجاد کنید
در این مرحله شما چند کلاس ایجاد می کنید تا در مرحله بعد از آنها استفاده کنید. طبقه بندی فرعی در یک کد آزمایشگاه قبلی پوشش داده شده بود، اما در اینجا یک بررسی مختصر وجود دارد.
- برای بی نظم نگه داشتن مثال، یک بسته جدید در زیر src ایجاد کنید و آن را
generics
. - در بسته ژنریک ، یک فایل
Aquarium.kt
جدید ایجاد کنید. این به شما امکان میدهد با استفاده از نامهای یکسان و بدون تداخل، چیزها را دوباره تعریف کنید، بنابراین بقیه کد شما برای این کد لبه وارد این فایل میشود. - سلسله مراتبی از انواع تامین آب ایجاد کنید. با تبدیل کردن
WaterSupply
به یک کلاسopen
شروع کنید تا بتوان آن را زیر کلاسبندی کرد. - یک پارامتر
var
boolean اضافه کنید،needsProcessing
. این به طور خودکار یک ویژگی قابل تغییر به همراه یک گیرنده و تنظیم کننده ایجاد می کند. - یک زیرکلاس
TapWater
کهWaterSupply
را گسترش می دهد و برایneedsProcessing
آن راtrue
بنویسید، زیرا آب لوله کشی حاوی مواد افزودنی است که برای ماهی مضر است. - در
TapWater
، تابعی به نامaddChemicalCleaners()
تعریف کنید که پس از تمیز کردن آب،needsProcessing
را رویfalse
قرار می دهد. ویژگیneedsProcessing
را می توان ازTapWater
تنظیم کرد، زیرا به طور پیش فرضpublic
است و برای زیر کلاس ها قابل دسترسی است. در اینجا کد تکمیل شده است.
package generics
open class WaterSupply(var needsProcessing: Boolean)
class TapWater : WaterSupply(true) {
fun addChemicalCleaners() {
needsProcessing = false
}
}
- دو زیر کلاس دیگر از
WaterSupply
به نام هایFishStoreWater
وLakeWater
کنید.FishStoreWater
نیازی به پردازش ندارد، اماLakeWater
باید با روشfilter()
شود. پس از فیلتر کردن، نیازی به پردازش مجدد نیست، بنابراین درfilter()
needsProcessing = false
را تنظیم کنید.
class FishStoreWater : WaterSupply(false)
class LakeWater : WaterSupply(true) {
fun filter() {
needsProcessing = false
}
}
اگر به اطلاعات بیشتری نیاز دارید، درس قبلی در مورد وراثت در کاتلین را مرور کنید.
مرحله 2: یک کلاس عمومی بسازید
در این مرحله کلاس Aquarium
را برای پشتیبانی از انواع مختلف منابع آب تغییر می دهید.
- در Aquarium.kt یک کلاس
Aquarium
را با<T>
در پرانتز بعد از نام کلاس تعریف کنید. - اضافه کردن یک ویژگی تغییر ناپذیر
waterSupply
از نوعT
بهAquarium
.
class Aquarium<T>(val waterSupply: T)
- تابعی به نام
genericsExample()
بنویسید. این بخشی از یک کلاس نیست، بنابراین می تواند در سطح بالای فایل مانند تابعmain()
یا تعاریف کلاس قرار گیرد. در عملکرد، یکAquarium
بسازید و آن را به عنوانWaterSupply
ارسال کنید. از آنجایی که پارامترwaterSupply
عمومی است، باید نوع آن را در براکت های زاویه ای<>
مشخص کنید.
fun genericsExample() {
val aquarium = Aquarium<TapWater>(TapWater())
}
- در
genericsExample()
کد شما می تواند بهwaterSupply
آکواریوم دسترسی داشته باشد. از آنجایی که از نوعTapWater
است، می توانیدaddChemicalCleaners()
را بدون هیچ نوع cast فراخوانی کنید.
fun genericsExample() {
val aquarium = Aquarium<TapWater>(TapWater())
aquarium.waterSupply.addChemicalCleaners()
}
- هنگام ایجاد آبجکت
Aquarium
، میتوانید براکتهای زاویه و آنچه را که بین آنها وجود دارد حذف کنید، زیرا کاتلین استنتاج نوع دارد. بنابراین دلیلی وجود ندارد که هنگام ایجاد نمونه، دو بار بگوییدTapWater
. نوع را می توان با استدلال بهAquarium
استنباط کرد. همچنان یکAquarium
از نوعTapWater
می سازد.
fun genericsExample() {
val aquarium = Aquarium(TapWater())
aquarium.waterSupply.addChemicalCleaners()
}
- برای دیدن آنچه اتفاق میافتد، قبل و بعد از فراخوانی
addChemicalCleaners()
needsProcessing
چاپ کنید. در زیر تابع کامل شده است.
fun genericsExample() {
val aquarium = Aquarium<TapWater>(TapWater())
println("water needs processing: ${aquarium.waterSupply.needsProcessing}")
aquarium.waterSupply.addChemicalCleaners()
println("water needs processing: ${aquarium.waterSupply.needsProcessing}")
}
- یک تابع
main()
برای فراخوانیgenericsExample()
اضافه کنید، سپس برنامه خود را اجرا کنید و نتیجه را مشاهده کنید.
fun main() {
genericsExample()
}
⇒ water needs processing: true water needs processing: false
مرحله 3: آن را مشخص تر کنید
عمومی به این معنی است که شما می توانید تقریباً هر چیزی را پاس کنید، و گاهی اوقات این یک مشکل است. در این مرحله کلاس Aquarium
را در مورد آنچه که می توانید در آن قرار دهید مشخص تر می کنید.
- در
genericsExample()
یکAquarium
ایجاد کنید و یک رشته برایwaterSupply
ارسال کنید، سپس ویژگیwaterSupply
آکواریوم را چاپ کنید.
fun genericsExample() {
val aquarium2 = Aquarium("string")
println(aquarium2.waterSupply)
}
- برنامه خود را اجرا کنید و نتیجه را مشاهده کنید.
⇒ string
نتیجه رشتهای است که پاس دادهاید، زیرا Aquarium
هیچ محدودیتی برای T.
ایجاد نمیکند. هر نوع، از جمله String
، میتواند به آن منتقل شود.
- در
genericsExample()
یکAquarium
دیگر ایجاد کنید که برایwaterSupply
null
میدهد. اگرwaterSupply
null است،"waterSupply is null"
را چاپ کنید.
fun genericsExample() {
val aquarium3 = Aquarium(null)
if (aquarium3.waterSupply == null) {
println("waterSupply is null")
}
}
- برنامه خود را اجرا کنید و نتیجه را مشاهده کنید.
⇒ waterSupply is null
چرا می توانید هنگام ایجاد یک Aquarium
، آن را null
؟ این ممکن است زیرا به طور پیش فرض، T
مخفف nullable Any?
نوع، نوع در بالای سلسله مراتب نوع. موارد زیر معادل همان چیزی است که قبلاً تایپ کردید.
class Aquarium<T: Any?>(val waterSupply: T)
- برای اینکه اجازه
T
null
Any
شود، با حذف?
بعد ازAny
.
class Aquarium<T: Any>(val waterSupply: T)
در این زمینه، Any
یک محدودیت عمومی نامیده می شود. این بدان معناست که هر نوع تا زمانی که null
نباشد، می تواند برای T
ارسال شود.
- آنچه واقعاً می خواهید این است که مطمئن شوید فقط یک
WaterSupply
(یا یکی از زیر کلاس های آن) می تواند برایT
ارسال شود. برای تعریف یک محدودیت عمومی خاص تر،Any
را باWaterSupply
جایگزین کنید.
class Aquarium<T: WaterSupply>(val waterSupply: T)
مرحله 4: بررسی بیشتر را اضافه کنید
در این مرحله با تابع check()
آشنا می شوید تا مطمئن شوید کد شما مطابق انتظار عمل می کند. تابع check()
یک تابع کتابخانه استاندارد در Kotlin است. این به عنوان یک ادعا عمل می کند و اگر آرگومان آن false
ارزیابی شود، یک IllegalStateException
می کند.
- یک
addWater()
را به کلاسAquarium
اضافه کنید تا آب اضافه کنید، با یکcheck()
که مطمئن می شود نیازی به پردازش آب ندارید.
class Aquarium<T: WaterSupply>(val waterSupply: T) {
fun addWater() {
check(!waterSupply.needsProcessing) { "water supply needs processing first" }
println("adding water from $waterSupply")
}
}
در این مورد، اگر needsProcessing
درست باشد، check()
یک استثنا ایجاد می کند.
- در
genericsExample()
کدی را برای ساختAquarium
باLakeWater
اضافه کنید و سپس مقداری آب به آن اضافه کنید.
fun genericsExample() {
val aquarium4 = Aquarium(LakeWater())
aquarium4.addWater()
}
- برنامه خود را اجرا کنید، یک استثنا خواهید داشت، زیرا ابتدا آب باید فیلتر شود.
⇒ Exception in thread "main" java.lang.IllegalStateException: water supply needs processing first at Aquarium.generics.Aquarium.addWater(Aquarium.kt:21)
- قبل از افزودن آب به
Aquarium
، تماسی برای فیلتر کردن آب اضافه کنید. اکنون وقتی برنامه خود را اجرا می کنید، هیچ استثنایی وجود ندارد.
fun genericsExample() {
val aquarium4 = Aquarium(LakeWater())
aquarium4.waterSupply.filter()
aquarium4.addWater()
}
⇒ adding water from generics.LakeWater@880ec60
موارد فوق اصول اولیه ژنریک را پوشش می دهد. وظایف زیر بیشتر را پوشش می دهد، اما مفهوم مهم این است که چگونه یک کلاس عمومی را با یک محدودیت عمومی اعلام و استفاده کنید.
در این کار، انواع درون و بیرون با ژنریک ها را یاد می گیرید. نوع in
نوعی است که فقط می تواند به یک کلاس منتقل شود، اما برگردانده نمی شود. نوع out
نوعی است که فقط از یک کلاس قابل بازگشت است.
به کلاس Aquarium
نگاه کنید و خواهید دید که نوع عمومی آن تنها با دریافت آب عرضه ملک waterSupply
می شود. هیچ روشی وجود ندارد که مقداری از نوع T
را به عنوان پارامتر بگیرد (به جز تعریف آن در سازنده). Kotlin به شما امکان می دهد انواع را دقیقاً برای این مورد تعریف out
، و می تواند اطلاعات اضافی در مورد محل استفاده از انواع بی خطر استنتاج کند. به طور مشابه، میتوانید انواعی را برای انواع عمومی تعریف in
که فقط به متدها منتقل میشوند و برگردانده نمیشوند. این به Kotlin اجازه می دهد تا بررسی های بیشتری را برای ایمنی کد انجام دهد.
انواع ورودی و out
دستورالعمل in
برای سیستم نوع کاتلین هستند. توضیح کل سیستم نوع خارج از محدوده این بوت کمپ است (بسیار درگیر است). با این حال، کامپایلر انواعی را که به طور مناسب به in
و out
علامت گذاری نشده اند، پرچم گذاری می کند، بنابراین باید در مورد آنها بدانید.
مرحله 1: یک نوع خارج را تعریف کنید
- در کلاس
Aquarium
،T: WaterSupply
را به یک نوعout
تغییر دهید.
class Aquarium<out T: WaterSupply>(val waterSupply: T) {
...
}
- در همان فایل، خارج از کلاس، تابع
addItemTo()
را که انتظار یکAquarium
WaterSupply
را دارد، اعلام کنید.
fun addItemTo(aquarium: Aquarium<WaterSupply>) = println("item added")
- از
addItemTo()
genericsExample()
کنید و برنامه خود را اجرا کنید.
fun genericsExample() {
val aquarium = Aquarium(TapWater())
addItemTo(aquarium)
}
⇒ item added
Kotlin میتواند اطمینان حاصل کند که addItemTo()
هیچ کاری از نوع ناامن با WaterSupply
عمومی انجام نمیدهد، زیرا بهعنوان یک نوع out
اعلام شده است.
- اگر کلمه کلیدی
out
را حذف کنید، کامپایلر هنگام فراخوانیaddItemTo()
با خطا مواجه میشود، زیرا کاتلین نمیتواند اطمینان حاصل کند که شما هیچ کاری ناامن با نوع انجام نمیدهید.
مرحله 2: نوع in را تعریف کنید
نوع in
شبیه به نوع out
است، اما برای انواع عمومی که فقط به توابع منتقل میشوند، برگردانده نمیشوند. اگر سعی کنید یک نوع in
را برگردانید، یک خطای کامپایلر دریافت خواهید کرد. در این مثال شما یک نوع in
را به عنوان بخشی از یک رابط تعریف می کنید.
- در Aquarium.kt ، یک Interface
Cleaner
را تعریف کنید که یکT
عمومی را می گیرد که بهWaterSupply
محدود شده است. از آنجایی که فقط به عنوان یک آرگومان برایclean()
استفاده می شود، می توانید آن را به یک پارامترin
تبدیل کنید.
interface Cleaner<in T: WaterSupply> {
fun clean(waterSupply: T)
}
- برای استفاده از رابط
Cleaner
، یک کلاسTapWaterCleaner
ایجاد کنید که با افزودن مواد شیمیایی،Cleaner
را برای تمیز کردنTapWater
پیاده سازی می کند.
class TapWaterCleaner : Cleaner<TapWater> {
override fun clean(waterSupply: TapWater) = waterSupply.addChemicalCleaners()
}
- در کلاس
Aquarium
،addWater()
را به روز کنید تا یکCleaner
از نوعT
بگیرد و قبل از اضافه کردن آب آن را تمیز کنید.
class Aquarium<out T: WaterSupply>(val waterSupply: T) {
fun addWater(cleaner: Cleaner<T>) {
if (waterSupply.needsProcessing) {
cleaner.clean(waterSupply)
}
println("water added")
}
}
- برای ایجاد یک
TapWaterCleaner
، یکAquarium
باTapWater
، کد نمونهgenericsExample()
را به روز کنید و سپس با استفاده از پاک کننده مقداری آب اضافه کنید. در صورت نیاز از پاک کننده استفاده می کند.
fun genericsExample() {
val cleaner = TapWaterCleaner()
val aquarium = Aquarium(TapWater())
aquarium.addWater(cleaner)
}
کاتلین از اطلاعات نوع ورودی و out
استفاده in
کند تا مطمئن شود کد شما به طور ایمن از ژنریک استفاده می کند. یادآوری کردن Out
و in
آسان است: انواع out
می توان به عنوان مقادیر بازگشتی به خارج ارسال کرد، in
انواع را می توان به عنوان آرگومان به داخل ارسال کرد.
اگر میخواهید بیشتر در مورد انواع مشکلات در انواع و انواع حلهای خارج تحقیق کنید، مستندات آنها را به طور عمیق پوشش میدهد.
در این کار با توابع عمومی و زمان استفاده از آنها آشنا می شوید. به طور معمول، هر زمان که تابع آرگومان کلاسی را بگیرد که دارای نوع عمومی است، ایجاد یک تابع عمومی ایده خوبی است.
مرحله 1: یک تابع عمومی بسازید
- در generics/Aquarium.kt ، یک تابع
isWaterClean()
که یکAquarium
می گیرد. باید نوع عمومی پارامتر را مشخص کنید. یکی از گزینه ها استفاده ازWaterSupply
است.
fun isWaterClean(aquarium: Aquarium<WaterSupply>) {
println("aquarium water is clean: ${aquarium.waterSupply.needsProcessing}")
}
اما این بدان معناست که Aquarium
برای فراخوانی آن باید یک پارامتر نوع out
داشته باشد. گاهی اوقات out
یا in
خیلی محدود کننده است زیرا باید از یک نوع برای ورودی و خروجی استفاده کنید. میتوانید با عمومی کردن تابع، نیاز out
را حذف کنید.
- برای عمومی کردن تابع، براکتهای زاویهای را بعد از کلمه کلیدی
fun
با نوعT
عمومی و هرگونه محدودیت، در این موردWaterSupply
قرار دهید.Aquarium
را تغییر دهید تا توسطT
به جایWaterSupply
شود.
fun <T: WaterSupply> isWaterClean(aquarium: Aquarium<T>) {
println("aquarium water is clean: ${!aquarium.waterSupply.needsProcessing}")
}
T
یک پارامتر نوع برای isWaterClean()
است که برای تعیین نوع عمومی آکواریوم استفاده می شود. این الگو واقعاً رایج است، و ایده خوبی است که کمی وقت بگذارید و روی آن کار کنید.
- تابع
isWaterClean()
را با مشخص کردن نوع آن در براکت های زاویه درست بعد از نام تابع و قبل از پرانتز فراخوانی کنید.
fun genericsExample() {
val aquarium = Aquarium(TapWater())
isWaterClean<TapWater>(aquarium)
}
- به دلیل استنتاج نوع از آرگومان
aquarium
، نوع مورد نیاز نیست، بنابراین آن را حذف کنید. برنامه خود را اجرا کنید و خروجی را مشاهده کنید.
fun genericsExample() {
val aquarium = Aquarium(TapWater())
isWaterClean(aquarium)
}
⇒ aquarium water is clean: false
مرحله 2: یک روش عمومی با نوع reified ایجاد کنید
شما می توانید از توابع عمومی برای متدها نیز استفاده کنید، حتی در کلاس هایی که نوع عمومی خود را دارند. در این مرحله، یک روش عمومی به Aquarium
اضافه میکنید که بررسی میکند که آیا یک نوع WaterSupply
دارد یا خیر.
- در کلاس
Aquarium
، یک متد به نامhasWaterSupplyOfType()
اعلام کنید که یک پارامتر عمومیR
(T
قبلاً استفاده شده است) را بهWaterSupply
محدود می کند، و اگرwaterSupply
از نوعR
باشد،true
را برمی گرداند. این مانند عملکردی است که قبلاً اعلام کردید، اما در کلاسAquarium
.
fun <R: WaterSupply> hasWaterSupplyOfType() = waterSupply is R
- توجه داشته باشید که
R
نهایی با رنگ قرمز خط کشیده شده است. نشانگر را روی آن نگه دارید تا ببینید خطا چیست. - برای انجام
is
بررسی، باید به Kotlin بگویید که نوع reified یا واقعی است و می تواند در تابع استفاده شود. برای انجام این کار، در مقابل کلمه کلیدیinline
قرارfun
و درreified
نوع عمومیR
.
inline fun <reified R: WaterSupply> hasWaterSupplyOfType() = waterSupply is R
هنگامی که یک نوع reified شد، می توانید از آن مانند یک نوع معمولی استفاده کنید - زیرا بعد از خط کشی یک نوع واقعی است. این بدان معنی است که شما می توانید با استفاده از is
بررسی کنید.
اگر در اینجا از reified
استفاده نمی کنید، نوع آن به اندازه کافی "واقعی" نخواهد بود که Kotlin بتواند چک is
را مجاز کند. دلیلش این است که انواع غیر اصلاحشده فقط در زمان کامپایل در دسترس هستند و در زمان اجرا توسط برنامه شما قابل استفاده نیستند. در بخش بعدی بیشتر به این موضوع پرداخته می شود.
-
TapWater
را به عنوان نوع عبور دهید. مانند فراخوانی توابع عمومی، روشهای عمومی را با استفاده از براکتهای زاویه با نوع بعد از نام تابع فراخوانی کنید. برنامه خود را اجرا کنید و نتیجه را مشاهده کنید.
fun genericsExample() {
val aquarium = Aquarium(TapWater())
println(aquarium.hasWaterSupplyOfType<TapWater>()) // true
}
⇒ true
مرحله 3: ایجاد توابع افزونه
می توانید از انواع reified برای توابع معمولی و توابع افزونه نیز استفاده کنید.
- خارج از کلاس
Aquarium
، یک تابع افزونه درWaterSupply
به نامisOfType()
تعریف کنید که بررسی می کند آیاWaterSupply
شده از نوع خاصی است، به عنوان مثال،TapWater
.
inline fun <reified T: WaterSupply> WaterSupply.isOfType() = this is T
- تابع افزونه را دقیقاً مانند یک متد فراخوانی کنید.
fun genericsExample() {
val aquarium = Aquarium(TapWater())
println(aquarium.waterSupply.isOfType<TapWater>())
}
⇒ true
با این توابع گسترش، مهم نیست که چه نوع Aquarium
باشد ( Aquarium
یا TowerTank
یا زیر کلاس دیگر)، تا زمانی که Aquarium
باشد. استفاده از سینتکس ستاره پرتاب یک راه راحت برای تعیین انواع تطابق است. و هنگامی که از یک ستاره پرتاب استفاده می کنید، کاتلین مطمئن می شود که شما نیز هیچ کاری ناامن انجام نمی دهید.
- برای استفاده از پرتاب ستاره،
<*>
را بعد ازAquarium
قرار دهید.hasWaterSupplyOfType()
را به عنوان یک تابع افزونه منتقل کنید، زیرا در واقع بخشی از API اصلیAquarium
نیست.
inline fun <reified R: WaterSupply> Aquarium<*>.hasWaterSupplyOfType() = waterSupply is R
- تماس را به
hasWaterSupplyOfType()
تغییر دهید و برنامه خود را اجرا کنید.
fun genericsExample() {
val aquarium = Aquarium(TapWater())
println(aquarium.hasWaterSupplyOfType<TapWater>())
}
⇒ true
در مثال قبلی، شما باید نوع عمومی را بهعنوان reified
علامتگذاری میکردید و تابع را inline
میکردید، زیرا کاتلین باید در زمان اجرا درباره آنها بداند، نه فقط زمان کامپایل.
همه انواع عمومی فقط در زمان کامپایل توسط Kotlin استفاده می شوند. این به کامپایلر امکان می دهد مطمئن شود که همه چیز را با خیال راحت انجام می دهید. در زمان اجرا همه انواع عمومی پاک می شوند، از این رو پیام خطای قبلی در مورد بررسی یک نوع پاک شده است.
به نظر می رسد که کامپایلر می تواند کد صحیح را بدون حفظ انواع عمومی تا زمان اجرا ایجاد کند. اما به این معنی است که گاهی اوقات کاری انجام می دهید is
مانند بررسی انواع عمومی، که کامپایلر نمی تواند آن را پشتیبانی کند. به همین دلیل است که کاتلین انواع reified یا واقعی را اضافه کرد.
می توانید اطلاعات بیشتری در مورد انواع اصلاح شده و پاک کردن نوع در اسناد Kotlin بخوانید.
این درس بر روی ژنریک تمرکز داشت که برای انعطافپذیری بیشتر کد و استفاده مجدد آسانتر از آن مهم است.
- کلاس های عمومی ایجاد کنید تا کد را انعطاف پذیرتر کنید.
- برای محدود کردن انواع مورد استفاده در ژنریک، محدودیتهای عمومی اضافه کنید.
-
in
انواع ورودی وout
با ژنریک استفاده کنید تا بررسی نوع بهتری را برای محدود کردن انواع ارسال یا بازگرداندن از کلاسها انجام دهید. - توابع و روش های عمومی را برای کار با انواع عمومی ایجاد کنید. مثلا:
fun <T: WaterSupply> isWaterClean(aquarium: Aquarium<T>) { ... }
- از توابع پسوند عمومی برای افزودن عملکردهای غیر اصلی به یک کلاس استفاده کنید.
- انواع Reified گاهی اوقات به دلیل پاک کردن نوع ضروری هستند. انواع Reified، بر خلاف انواع عمومی، تا زمان اجرا باقی می مانند.
- از تابع
check()
برای تأیید اینکه کد شما مطابق انتظار اجرا می شود استفاده کنید. مثلا:
check(!waterSupply.needsProcessing) { "water supply needs processing first" }
مستندات کاتلین
اگر در مورد هر موضوعی در این دوره اطلاعات بیشتری می خواهید، یا اگر گیر کرده اید، https://kotlinlang.org بهترین نقطه شروع شما است.
- ژنریک ها
- محدودیت های عمومی
- پیش بینی های ستاره ای
- انواع
In
وout
- پارامترهای Reified
- پاک کردن را تایپ کنید
- تابع
check()
آموزش های کاتلین
وبسایت https://try.kotlinlang.org شامل آموزشهای غنی به نام Kotlin Koans، یک مترجم مبتنی بر وب و مجموعه کاملی از مستندات مرجع با مثال است.
دوره جسارت
برای مشاهده دوره Udacity در مورد این موضوع، به Kotlin Bootcamp for Programmers مراجعه کنید.
ایده IntelliJ
اسناد IntelliJ IDEA را می توان در وب سایت JetBrains یافت.
این بخش، تکالیف احتمالی را برای دانشآموزانی که در این آزمایشگاه کد به عنوان بخشی از دورهای که توسط یک مربی هدایت میشود، فهرست میکند. این وظیفه مربی است که موارد زیر را انجام دهد:
- در صورت نیاز تکالیف را تعیین کنید.
- نحوه ارسال تکالیف را با دانش آموزان در میان بگذارید.
- تکالیف را نمره دهید.
مربیان میتوانند از این پیشنهادات به اندازهای که میخواهند استفاده کنند، و باید با خیال راحت هر تکلیف دیگری را که فکر میکنند مناسب است به آنها اختصاص دهند.
اگر به تنهایی بر روی این کدها کار می کنید، از این تکالیف برای آزمایش دانش خود استفاده کنید.
به این سوالات پاسخ دهید
سوال 1
کدام یک از موارد زیر برای نامگذاری یک نوع عمومی مناسب است؟
▢ <Gen>
▢ <Generic>
▢ <T>
▢ <X>
سوال 2
محدودیت در انواع مجاز برای یک نوع عمومی نامیده می شود:
▢ یک محدودیت عمومی
▢ یک محدودیت عمومی
▢ ابهام زدایی
▢ محدودیت نوع عمومی
سوال 3
ریفید یعنی:
▢ تاثیر اجرای واقعی یک شی محاسبه شده است.
▢ یک شاخص ورودی محدود روی کلاس تنظیم شده است.
▢ پارامتر نوع عمومی به یک نوع واقعی تبدیل شده است.
▢ نشانگر خطای راه دور فعال شده است.
به درس بعدی بروید:
برای یک نمای کلی از دوره، از جمله پیوندهایی به دیگر کد لبه ها، به «کوتلین بوت کمپ برای برنامه نویسان: به دوره خوش آمدید» مراجعه کنید.