این Codelab بخشی از دوره Kotlin Bootcamp برای برنامه نویسان است . اگر به ترتیب روی کدها کار کنید، بیشترین ارزش را از این دوره خواهید گرفت. بسته به دانش خود، ممکن است بتوانید برخی از بخش ها را مرور کنید. این دوره برای برنامه نویسانی است که زبان شی گرا را می دانند و می خواهند Kotlin را یاد بگیرند.
مقدمه
در این کد لبه، شما یک برنامه Kotlin ایجاد می کنید و با توابع در Kotlin، از جمله مقادیر پیش فرض پارامترها، فیلترها، لامبداها و توابع فشرده آشنا می شوید.
به جای ساختن یک برنامه نمونه واحد، درسهای این دوره برای ایجاد دانش شما طراحی شدهاند، اما نیمه مستقل از یکدیگر باشند تا بتوانید بخشهایی را که با آنها آشنا هستید، مرور کنید. برای گره زدن آنها به یکدیگر، بسیاری از نمونه ها از تم آکواریوم استفاده می کنند. و اگر می خواهید داستان کامل آکواریوم را ببینید، دوره Kotlin Bootcamp for Programmers Udacity را بررسی کنید.
آنچه از قبل باید بدانید
- اصول یک زبان برنامه نویسی مدرن، شی گرا و تایپ ایستا
- نحوه برنامه نویسی با کلاس ها، متدها و مدیریت استثنا در حداقل یک زبان
- نحوه کار با Kotlin's REPL (Read-Eval-Print Loop) در IntelliJ IDEA
- اصول اولیه Kotlin، از جمله انواع، عملگرها و حلقه ها
این کد لبه برای برنامه نویسانی طراحی شده است که یک زبان شی گرا را می دانند و می خواهند در مورد Kotlin اطلاعات بیشتری کسب کنند.
چیزی که یاد خواهید گرفت
- نحوه ایجاد یک برنامه با تابع
main()
و آرگومان در IntelliJ IDEA - نحوه استفاده از مقادیر پیش فرض و توابع فشرده
- نحوه اعمال فیلتر برای لیست ها
- نحوه ایجاد لامبداهای پایه و توابع درجه بالاتر
کاری که خواهی کرد
- برای امتحان کردن کد با REPL کار کنید.
- برای ایجاد برنامه های اساسی Kotlin با IntelliJ IDEA کار کنید.
در این کار، یک برنامه Kotlin ایجاد میکنید و با تابع main()
و همچنین نحوه ارسال آرگومانها به برنامه از خط فرمان آشنا میشوید.
ممکن است تابع printHello()
را که در REPL در لبه کد قبلی وارد کرده بودید به خاطر بیاورید:
fun printHello() {
println ("Hello World")
}
printHello()
⇒ Hello World
توابع را با استفاده از کلمه کلیدی fun
و به دنبال آن نام تابع تعریف می کنید. مانند سایر زبان های برنامه نویسی، پرانتز ()
برای آرگومان های تابع، در صورت وجود، است. پرانتزهای فرفری {}
کد تابع را قاب می کنند. هیچ نوع بازگشتی برای این تابع وجود ندارد، زیرا چیزی بر نمی گرداند.
مرحله 1: یک فایل Kotlin ایجاد کنید
- IntelliJ IDEA را باز کنید.
- پنجره Project در سمت چپ IntelliJ IDEA لیستی از فایل ها و پوشه های پروژه شما را نشان می دهد. پوشه src را در زیر Hello Kotlin پیدا کرده و کلیک راست کنید. (شما از قبل باید پروژه Hello Kotlin را از نرم افزار کد قبلی داشته باشید.)
- New > Kotlin File / Class را انتخاب کنید.
- Kind as File را نگه دارید و نام فایل را Hello بگذارید .
- روی OK کلیک کنید.
اکنون یک فایل در پوشه src به نام Hello.kt وجود دارد.
مرحله 2: کد اضافه کنید و برنامه خود را اجرا کنید
- همانند سایر زبان ها، تابع
main()
Kotlin نقطه ورودی را برای اجرا مشخص می کند. هر آرگومان خط فرمان به عنوان آرایه ای از رشته ها ارسال می شود.
کد زیر را تایپ کرده یا در فایل Hello.kt قرار دهید :
fun main(args: Array<String>) {
println("Hello, world!")
}
مانند تابع printHello()
قبلی شما، این تابع هیچ عبارت return
ندارد. هر تابع در Kotlin چیزی را برمی گرداند، حتی زمانی که هیچ چیز به صراحت مشخص نشده باشد. بنابراین تابعی مانند این تابع main()
یک نوع kotlin.Unit
را برمیگرداند، که روش کاتلین برای گفتن هیچ مقدار است.
- برای اجرای برنامه خود، روی مثلث سبز رنگ سمت چپ تابع
main()
کلیک کنید. Run 'HelloKt' را از منو انتخاب کنید. - IntelliJ IDEA برنامه را کامپایل کرده و اجرا می کند. نتایج در یک صفحه گزارش در پایین ظاهر می شود، همانطور که در زیر نشان داده شده است.
مرحله 3: ارسال آرگومان ها به main()
از آنجایی که شما برنامه خود را از IntelliJ IDEA اجرا می کنید و نه از خط فرمان، باید هر آرگومان را برای برنامه کمی متفاوت مشخص کنید.
- Run > Edit Configurations را انتخاب کنید. پنجره Run/Debug Configurations باز می شود.
-
Kotlin!
در قسمت Program arguments . - روی OK کلیک کنید.
مرحله 4: کد را برای استفاده از یک قالب رشته تغییر دهید
یک قالب رشته یک متغیر یا عبارت را در یک رشته وارد می کند و $
مشخص می کند که بخشی از رشته یک متغیر یا عبارت باشد. در صورت وجود، پرانتزهای فرفری {}
عبارت را قاب میکنند.
- در Hello.kt ، پیام تبریک را تغییر دهید تا از اولین آرگومان ارسال شده به برنامه،
args[0]
به جای"world"
استفاده کنید.
fun main(args: Array<String>) {
println("Hello, ${args[0]}")
}
- برنامه را اجرا کنید و خروجی شامل آرگومانی است که شما مشخص کرده اید.
⇒ Hello, Kotlin!
در این کار، می آموزید که چرا تقریباً همه چیز در کاتلین ارزش دارد و چرا این کار مفید است.
برخی از زبانهای دیگر عبارتهایی دارند که خطوط کدی هستند که مقداری ندارند. در Kotlin، تقریباً همه چیز یک عبارت است و یک مقدار دارد - حتی اگر آن مقدار kotlin.Unit
باشد.
- در Hello.kt کدی را در
main()
بنویسید تا یکprintln()
به متغیری به نامisUnit
و آن را چاپ کنید. (println()
مقداری را برمی گرداند، بنابراینkotlin.Unit
را برمی گرداند.)
// Will assign kotlin.Unit
val isUnit = println("This is an expression")
println(isUnit)
- برنامه خود را اجرا کنید اولین
println()
رشته"This is an expression"
را چاپ می کند. دومینprintln()
مقدار اولین دستورprintln()
() را چاپ می کند، یعنیkotlin.Unit
.
⇒ This is an expression kotlin.Unit
- یک
val
به نامtemperature
اعلام کنید و آن را به 10 مقداردهی کنید. - مقدار دیگری به نام
val
را اعلام کنید و مقدار بازگشتی یک عبارتif
/else
را همانطور که در کد زیر نشان داده شده است بهisHot
isHot
. از آنجایی که یک عبارت است، می توانید بلافاصله از مقدار عبارتif
استفاده کنید.
val temperature = 10
val isHot = if (temperature > 50) true else false
println(isHot)
⇒ false
- از مقدار یک عبارت در قالب رشته استفاده کنید. مقداری کد اضافه کنید تا دما را بررسی کنید تا بفهمید ماهی ایمن است یا خیلی گرم است، سپس برنامه خود را اجرا کنید.
val temperature = 10
val message = "The water temperature is ${ if (temperature > 50) "too warm" else "OK" }."
println(message)
⇒ The water temperature is OK.
در این کار، شما بیشتر در مورد توابع در Kotlin، و در مورد بیان شرطی بسیار مفید when
می گیرید.
مرحله 1: ایجاد برخی از توابع
در این مرحله، برخی از آموخته های خود را کنار هم می گذارید و توابع با انواع مختلف ایجاد می کنید. می توانید محتویات Hello.kt را با این کد جدید جایگزین کنید.
- تابعی به نام
feedTheFish()
بنویسید کهrandomDay()
() را فراخوانی می کند تا یک روز تصادفی در هفته بدست آید. از یک الگوی رشته ای برای چاپfood
که ماهی در آن روز بخورد استفاده کنید. در حال حاضر، ماهی ها هر روز همان غذا را می خورند.
fun feedTheFish() {
val day = randomDay()
val food = "pellets"
println ("Today is $day and the fish eat $food")
}
fun main(args: Array<String>) {
feedTheFish()
}
- تابع
randomDay()
را بنویسید تا یک روز تصادفی از یک آرایه انتخاب کرده و آن را برگرداند.
nextInt()
یک محدودیت عدد صحیح می گیرد، که عدد را از Random()
به 0 تا 6 محدود می کند تا با آرایه week
مطابقت داشته باشد.
fun randomDay() : String {
val week = arrayOf ("Monday", "Tuesday", "Wednesday", "Thursday",
"Friday", "Saturday", "Sunday")
return week[Random().nextInt(week.size)]
}
- توابع
Random()
وnextInt()
درjava.util.*
تعریف شده اند. در بالای فایل، وارد کردن مورد نیاز را اضافه کنید:
import java.util.* // required import
- برنامه خود را اجرا کنید و خروجی را بررسی کنید.
⇒ Today is Tuesday and the fish eat pellets
مرحله 2: از عبارت When استفاده کنید
با گسترش بیشتر، کد را برای انتخاب غذاهای مختلف برای روزهای مختلف با استفاده از عبارت when
تغییر دهید. دستور when
مشابه switch
در سایر زبان های برنامه نویسی است، اما when
به طور خودکار در انتهای هر شاخه شکسته می شود. همچنین مطمئن می شود که کد شما تمام شاخه ها را پوشش می دهد اگر در حال بررسی یک enum هستید.
- در Hello.kt ، تابعی به نام
fishFood()
اضافه کنید که یک روز به عنوانString
طول می کشد و غذای ماهی را برای آن روز به صورتString
برمی گرداند. ازwhen()
استفاده کنید تا ماهی هر روز غذای خاصی دریافت کند. برنامه خود را چند بار اجرا کنید تا خروجی های مختلف را ببینید.
fun fishFood (day : String) : String {
var food = ""
when (day) {
"Monday" -> food = "flakes"
"Tuesday" -> food = "pellets"
"Wednesday" -> food = "redworms"
"Thursday" -> food = "granules"
"Friday" -> food = "mosquitoes"
"Saturday" -> food = "lettuce"
"Sunday" -> food = "plankton"
}
return food
}
fun feedTheFish() {
val day = randomDay()
val food = fishFood(day)
println ("Today is $day and the fish eat $food")
}
⇒ Today is Thursday and the fish eat granules
- یک شاخه پیش فرض را به عبارت
when
با استفاده ازelse
اضافه کنید. برای تست، برای اینکه مطمئن شوید گاهی اوقات پیش فرض در برنامه شما گرفته شده است، شاخه هایTuesday
وSaturday
را حذف کنید.
داشتن یک شاخه پیش فرض تضمین می کند کهfood
قبل از بازگرداندن مقداری دریافت می کند، بنابراین دیگر نیازی به مقداردهی اولیه نیست. از آنجایی که کد اکنون فقط یک بار بهfood
یک رشته اختصاص می دهد، می توانیدfood
را به جایvar
باval
اعلان کنید.
fun fishFood (day : String) : String {
val food : String
when (day) {
"Monday" -> food = "flakes"
"Wednesday" -> food = "redworms"
"Thursday" -> food = "granules"
"Friday" -> food = "mosquitoes"
"Sunday" -> food = "plankton"
else -> food = "nothing"
}
return food
}
- از آنجا که هر عبارت دارای یک مقدار است، می توانید این کد را کمی مختصرتر کنید. مقدار عبارت
when
را مستقیماً برگردانید و متغیرfood
را حذف کنید. مقدار عبارتwhen
مقدار آخرین عبارت شاخه ای است که شرط را برآورده می کند.
fun fishFood (day : String) : String {
return when (day) {
"Monday" -> "flakes"
"Wednesday" -> "redworms"
"Thursday" -> "granules"
"Friday" -> "mosquitoes"
"Sunday" -> "plankton"
else -> "nothing"
}
}
نسخه نهایی برنامه شما چیزی شبیه به کد زیر است.
import java.util.* // required import
fun randomDay() : String {
val week = arrayOf ("Monday", "Tuesday", "Wednesday", "Thursday",
"Friday", "Saturday", "Sunday")
return week[Random().nextInt(week.size)]
}
fun fishFood (day : String) : String {
return when (day) {
"Monday" -> "flakes"
"Wednesday" -> "redworms"
"Thursday" -> "granules"
"Friday" -> "mosquitoes"
"Sunday" -> "plankton"
else -> "nothing"
}
}
fun feedTheFish() {
val day = randomDay()
val food = fishFood(day)
println ("Today is $day and the fish eat $food")
}
fun main(args: Array<String>) {
feedTheFish()
}
در این کار با مقادیر پیش فرض توابع و متدها آشنا می شوید. همچنین با توابع فشرده آشنا می شوید که می تواند کد شما را مختصرتر و خواناتر کند و تعداد مسیرهای کد را برای آزمایش کاهش دهد. توابع فشرده را توابع تک بیانی نیز می نامند.
مرحله 1: یک مقدار پیش فرض برای یک پارامتر ایجاد کنید
در Kotlin، می توانید آرگومان ها را با نام پارامتر ارسال کنید. همچنین میتوانید مقادیر پیشفرض را برای پارامترها مشخص کنید: اگر آرگومان توسط تماسگیرنده ارائه نشود، از مقدار پیشفرض استفاده میشود. بعداً، وقتی متدها (توابع عضو) را مینویسید، به این معنی است که میتوانید از نوشتن نسخههای اضافه بار زیادی از همان روش اجتناب کنید.
- در Hello.kt ، یک تابع
swim()
با پارامترString
به نامspeed
بنویسید که سرعت ماهی را چاپ می کند. پارامترspeed
دارای مقدار پیش فرض"fast"
است.
fun swim(speed: String = "fast") {
println("swimming $speed")
}
- از تابع
main()
تابعswim()
را به سه روش فراخوانی کنید. ابتدا تابع را با استفاده از پیش فرض فراخوانی کنید. سپس تابع را فراخوانی کرده و پارامترspeed
را بدون نام ارسال کنید، سپس با نامگذاری پارامترspeed
، تابع را فراخوانی کنید.
swim() // uses default speed
swim("slow") // positional argument
swim(speed="turtle-like") // named parameter
⇒ swimming fast swimming slow swimming turtle-like
مرحله 2: پارامترهای مورد نیاز را اضافه کنید
اگر هیچ پیش فرضی برای یک پارامتر مشخص نشده باشد، آرگومان مربوطه باید همیشه ارسال شود.
- در Hello.kt ، یک
shouldChangeWater()
که سه پارامترday
،temperature
و سطحdirty
را می گیرد. اگر آب باید عوض شود، عملکردtrue
برمیگردد، که اگر یکشنبه باشد، اگر دما خیلی بالا باشد یا اگر آب خیلی کثیف باشد، این اتفاق میافتد. روز هفته الزامی است، اما دمای پیش فرض 22 و سطح کثیف پیش فرض 20 است.
از عبارتwhen
بدون آرگومان استفاده کنید، که در Kotlin به عنوان یک سری چک هایif/else if
عمل می کند.
fun shouldChangeWater (day: String, temperature: Int = 22, dirty: Int = 20): Boolean {
return when {
temperature > 30 -> true
dirty > 30 -> true
day == "Sunday" -> true
else -> false
}
}
- با
shouldChangeWater()
shouldChangeWater ازfeedTheFish()
تماس بگیرید و روز را عرضه کنید. پارامترday
پیشفرض ندارد، بنابراین باید یک آرگومان مشخص کنید. دو پارامتر دیگرshouldChangeWater()
دارای مقادیر پیشفرض هستند، بنابراین نیازی به ارسال آرگومان برای آنها ندارید.
fun feedTheFish() {
val day = randomDay()
val food = fishFood(day)
println ("Today is $day and the fish eat $food")
println("Change water: ${shouldChangeWater(day)}")
}
=> Today is Thursday and the fish eat granules Change water: false
مرحله 3: توابع فشرده بسازید
عبارت when
که در مرحله قبل نوشتید، منطق زیادی را در مقدار کمی کد بسته بندی می کند. اگر میخواهید آن را کمی باز کنید، یا اگر شرایط بررسی پیچیدهتر بود، میتوانید از چند متغیر محلی با نام خوب استفاده کنید. اما راه کاتلین برای انجام آن با توابع فشرده است.
توابع فشرده یا توابع تک بیانی ، یک الگوی رایج در کاتلین هستند. هنگامی که یک تابع نتایج یک عبارت واحد را برمی گرداند، می توانید بدنه تابع را بعد از علامت =
مشخص کنید، پرانتزهای فرفری {}
را حذف کنید و return
را حذف کنید.
- در Hello.kt ، توابع فشرده را برای آزمایش شرایط اضافه کنید.
fun isTooHot(temperature: Int) = temperature > 30
fun isDirty(dirty: Int) = dirty > 30
fun isSunday(day: String) = day == "Sunday"
- برای فراخوانی توابع جدید
shouldChangeWater()
را تغییر دهید.
fun shouldChangeWater (day: String, temperature: Int = 22, dirty: Int = 20): Boolean {
return when {
isTooHot(temperature) -> true
isDirty(dirty) -> true
isSunday(day) -> true
else -> false
}
}
- برنامه خود را اجرا کنید خروجی
println()
باshouldChangeWater()
باید همان چیزی باشد که قبل از استفاده از توابع فشرده بود.
مقادیر پیش فرض
مقدار پیش فرض برای یک پارامتر لازم نیست یک مقدار باشد. می تواند تابع دیگری باشد، همانطور که در نمونه جزئی زیر نشان داده شده است:
fun shouldChangeWater (day: String, temperature: Int = 22, dirty: Int = getDirtySensorReading()): Boolean {
...
در این کار کمی با فیلترها در Kotlin آشنا می شوید. فیلترها روشی مفید برای دریافت بخشی از لیست بر اساس برخی شرایط هستند.
مرحله 1: یک فیلتر ایجاد کنید
- در Hello.kt ، فهرستی از تزئینات آکواریوم را در سطح بالایی با
listOf()
کنید. می توانید محتویات Hello.kt را جایگزین کنید.
val decorations = listOf ("rock", "pagoda", "plastic plant", "alligator", "flowerpot")
- یک تابع
main()
جدید با یک خط ایجاد کنید تا فقط تزئیناتی را که با حرف 'p' شروع می شوند چاپ کنید. کد شرایط فیلتر در پرانتزهای مجعد{}
است وit
هر مورد اشاره میکند که فیلتر از میان آن عبور میکند. اگر عبارتtrue
را برگرداند، مورد شامل می شود.
fun main() {
println( decorations.filter {it[0] == 'p'})
}
- برنامه خود را اجرا کنید و خروجی زیر را در پنجره Run مشاهده می کنید:
⇒ [pagoda, plastic plant]
مرحله 2: فیلترهای مشتاق و تنبل را مقایسه کنید
اگر با فیلترها در زبان های دیگر آشنا هستید، ممکن است تعجب کنید که آیا فیلترها در Kotlin مشتاق هستند یا تنبل . آیا لیست نتایج بلافاصله ایجاد می شود یا زمانی که به لیست دسترسی پیدا کرد؟ در کاتلین، به هر شکلی که نیاز داشته باشید، اتفاق می افتد. به طور پیش فرض، filter
مشتاق است و هر بار که از فیلتر استفاده می کنید، یک لیست ایجاد می شود.
برای تنبل کردن فیلتر، میتوانید از یک Sequence
استفاده کنید، که مجموعهای است که میتواند هر بار فقط به یک مورد نگاه کند، از ابتدا تا انتها میرود. به راحتی، این دقیقا همان API است که یک فیلتر تنبل به آن نیاز دارد.
- در Hello.kt ، کد خود را تغییر دهید تا لیست فیلتر شده را به متغیری به نام
eager
اختصاص دهید، سپس آن را چاپ کنید.
fun main() {
val decorations = listOf ("rock", "pagoda", "plastic plant", "alligator", "flowerpot")
// eager, creates a new list
val eager = decorations.filter { it [0] == 'p' }
println("eager: " + eager)
- در زیر آن کد، فیلتر را با استفاده از
Sequence
باasSequence()
کنید. دنباله را به متغیری به نامfiltered
اختصاص دهید و آن را چاپ کنید.
// lazy, will wait until asked to evaluate
val filtered = decorations.asSequence().filter { it[0] == 'p' }
println("filtered: " + filtered)
هنگامی که نتایج فیلتر را بهعنوان یک Sequence
، متغیر filtered
فهرست جدیدی را در خود نگه نمیدارد - یک Sequence
از عناصر لیست و دانش فیلتر را برای اعمال به آن عناصر نگه میدارد. هر زمان که به عناصر Sequence
دسترسی پیدا کردید، فیلتر اعمال می شود و نتیجه به شما بازگردانده می شود.
- ارزیابی اجباری دنباله را با تبدیل آن به
List
با استفاده ازtoList()
. نتیجه را چاپ کنید.
// force evaluation of the lazy list
val newList = filtered.toList()
println("new list: " + newList)
- برنامه خود را اجرا کنید و خروجی را مشاهده کنید.
⇒ eager: [pagoda, plastic plant] filtered: kotlin.sequences.FilteringSequence@386cc1c4 new list: [pagoda, plastic plant]
برای تجسم آنچه در ارزیابی Sequence
و Lazy در حال انجام است، از تابع map()
استفاده کنید. تابع map()
یک تبدیل ساده روی هر عنصر در دنباله انجام می دهد.
- با همان لیست
decorations
بالا، یک تبدیل باmap()
ایجاد کنید که هیچ کاری انجام نمی دهد و به سادگی عنصری را که ارسال شده برمی گرداند. برای نمایش هر بار دسترسی به یک عنصر، یکprintln()
اضافه کنید و دنباله را به متغیری به نامlazyMap
.
val lazyMap = decorations.asSequence().map {
println("access: $it")
it
}
-
lazyMap
را چاپ کنید، اولین عنصرlazyMap
را با استفاده ازfirst()
چاپ کنید، وlazyMap
را که بهList
تبدیل شده است چاپ کنید.
println("lazy: $lazyMap")
println("-----")
println("first: ${lazyMap.first()}")
println("-----")
println("all: ${lazyMap.toList()}")
- برنامه خود را اجرا کنید و خروجی را مشاهده کنید. چاپ
lazyMap
فقط یک ارجاع بهSequence
را چاپ می کند —println()
داخلی نامیده نمی شود. چاپ عنصر اول فقط به عنصر اول دسترسی دارد. تبدیلSequence
به یکList
به همه عناصر دسترسی دارد.
⇒ lazy: kotlin.sequences.TransformingSequence@5ba23b66 ----- access: rock first: rock ----- access: rock access: pagoda access: plastic plant access: alligator access: flowerpot all: [rock, pagoda, plastic plant, alligator, flowerpot]
- قبل از اعمال
map
با استفاده از فیلتر اصلی یکSequence
جدید ایجاد کنید. آن نتیجه را چاپ کنید.
val lazyMap2 = decorations.asSequence().filter {it[0] == 'p'}.map {
println("access: $it")
it
}
println("-----")
println("filtered: ${ lazyMap2.toList() }")
- برنامه خود را اجرا کنید و خروجی اضافی را مشاهده کنید. همانند دریافت اولین عنصر،
println()
داخلی فقط برای عناصری که به آنها دسترسی دارند فراخوانی می شود.
⇒ ----- access: pagoda access: plastic plant filtered: [pagoda, plastic plant]
در این کار، شما با لامبداها و توابع درجه بالاتر در Kotlin آشنا می شوید.
لامبدا
علاوه بر توابع نامگذاری شده سنتی، کاتلین از لامبدا پشتیبانی می کند. لامبدا عبارتی است که یک تابع را می سازد. اما به جای اعلان یک تابع با نام، تابعی را اعلام می کنید که نام ندارد. بخشی از چیزی که این را مفید می کند این است که عبارت لامبدا اکنون می تواند به عنوان داده ارسال شود. در زبانهای دیگر، لامبدا را توابع ناشناس ، توابع تحت اللفظی یا نامهای مشابه میگویند.
توابع مرتبه بالاتر
شما می توانید با ارسال یک لامبدا به تابع دیگر، یک تابع مرتبه بالاتر ایجاد کنید. در کار قبلی، یک تابع مرتبه بالاتر به نام filter
ایجاد کردید. شما عبارت لامبدا زیر را به عنوان شرط بررسی برای filter
کردن:
{it[0] == 'p'}
به طور مشابه، map
یک تابع مرتبه بالاتر است، و لامبدای که به آن ارسال کردید، تبدیلی بود که باید اعمال شود.
مرحله 1: با لامبدا آشنا شوید
- مانند توابع نامگذاری شده، لامبداها می توانند پارامترهایی داشته باشند. برای لامبداها، پارامترها (و انواع آنها، در صورت نیاز) در سمت چپ چیزی که فلش تابع نامیده می شود
->
می رود. کدی که باید اجرا شود به سمت راست فلش تابع می رود. هنگامی که لامبدا به یک متغیر اختصاص داده می شود، می توانید آن را درست مانند یک تابع فراخوانی کنید.
با استفاده از REPL ( Tools > Kotlin > Kotlin REPL )، این کد را امتحان کنید:
var dirtyLevel = 20
val waterFilter = { dirty : Int -> dirty / 2}
println(waterFilter(dirtyLevel))
⇒ 10
در این مثال، لامبدا یک Int
به نام dirty
می گیرد و dirty / 2
را برمی گرداند. (زیرا فیلتر کردن کثیفی را از بین می برد.)
- نحو کاتلین برای انواع توابع ارتباط نزدیکی با نحو آن برای لامبدا دارد. از این نحو استفاده کنید تا متغیری را که دارای تابعی است به طور تمیز اعلام کنید:
val waterFilter: (Int) -> Int = { dirty -> dirty / 2 }
این چیزی است که کد می گوید:
- یک متغیر به نام
waterFilter
. -
waterFilter
می تواند هر تابعی باشد که یکInt
بگیرد و یکInt
برگرداند. - یک لامبدا را به
waterFilter
اختصاص دهید. - لامبدا مقدار آرگومان
dirty
را تقسیم بر 2 برمی گرداند.
توجه داشته باشید که دیگر لازم نیست نوع آرگومان لامبدا را مشخص کنید. نوع با استنتاج نوع محاسبه می شود.
مرحله 2: یک تابع مرتبه بالاتر ایجاد کنید
تاکنون، نمونههای لامبدا بیشتر شبیه توابع هستند. قدرت واقعی لامبداها استفاده از آنها برای ایجاد توابع مرتبه بالاتر است، جایی که آرگومان یک تابع تابع دیگری است.
- یک تابع مرتبه بالاتر بنویسید. در اینجا یک مثال اساسی وجود دارد، تابعی که دو آرگومان می گیرد. آرگومان اول یک عدد صحیح است. آرگومان دوم تابعی است که یک عدد صحیح می گیرد و یک عدد صحیح برمی گرداند. آن را در REPL امتحان کنید.
fun updateDirty(dirty: Int, operation: (Int) -> Int): Int {
return operation(dirty)
}
بدنه کد تابعی را که به عنوان آرگومان دوم ارسال شده است فراخوانی می کند و آرگومان اول را به آن ارسال می کند.
- برای فراخوانی این تابع، آن را یک عدد صحیح و یک تابع ارسال کنید.
val waterFilter: (Int) -> Int = { dirty -> dirty / 2 }
println(updateDirty(30, waterFilter))
⇒ 15
تابعی که پاس می کنید لازم نیست لامبدا باشد. در عوض می تواند یک تابع با نام معمولی باشد. برای تعیین آرگومان به عنوان یک تابع منظم، از عملگر ::
استفاده کنید. به این ترتیب کاتلین می داند که شما مرجع تابع را به عنوان آرگومان ارسال می کنید، نه اینکه سعی کنید تابع را فراخوانی کنید.
- سعی کنید یک تابع با نام معمولی را به
updateDirty()
.
fun increaseDirty( start: Int ) = start + 1
println(updateDirty(15, ::increaseDirty))
⇒ 16
var dirtyLevel = 19;
dirtyLevel = updateDirty(dirtyLevel) { dirtyLevel -> dirtyLevel + 23}
println(dirtyLevel)
⇒ 42
- برای ایجاد یک فایل منبع Kotlin در IntelliJ IDEA، با یک پروژه Kotlin شروع کنید.
- برای کامپایل و اجرای یک برنامه در IntelliJ IDEA، روی مثلث سبز کنار تابع
main()
کلیک کنید. خروجی در یک پنجره ورود به سیستم در زیر ظاهر می شود. - در IntelliJ IDEA، آرگومان های خط فرمان را برای انتقال به تابع
main()
در Run > Edit Configurations مشخص کنید. - تقریباً همه چیز در کاتلین ارزشی دارد. با استفاده از مقدار
if
یاwhen
به عنوان یک عبارت یا مقدار بازگشتی، می توانید از این واقعیت برای مختصرتر کردن کد خود استفاده کنید. - آرگومان های پیش فرض نیاز به چندین نسخه از یک تابع یا متد را برطرف می کند. مثلا:
fun swim(speed: String = "fast") { ... }
- توابع فشرده یا توابع تک بیانی می توانند کد شما را خواناتر کنند. مثلا:
fun isTooHot(temperature: Int) = temperature > 30
- شما برخی از اصول اولیه فیلترها را یاد گرفته اید که از عبارات لامبدا استفاده می کنند. مثلا:
val beginsWithP = decorations.filter { it [0] == 'p' }
- عبارت lambda عبارتی است که یک تابع بدون نام ایجاد می کند. عبارات لامبدا بین پرانتزهای فرفری
{}
تعریف می شوند. - در یک تابع مرتبه بالاتر ، تابعی مانند عبارت لامبدا را به تابع دیگری به عنوان داده ارسال می کنید. مثلا:
dirtyLevel = updateDirty(dirtyLevel) { dirtyLevel -> dirtyLevel + 23}
در این درس چیزهای زیادی وجود دارد، به خصوص اگر تازه با لامبدا آشنا شده اید. درس بعدی به بررسی مجدد لامبداها و توابع مرتبه بالاتر می پردازد.
مستندات کاتلین
اگر در مورد هر موضوعی در این دوره اطلاعات بیشتری می خواهید، یا اگر گیر کرده اید، https://kotlinlang.org بهترین نقطه شروع شما است.
- قالب های رشته ای
-
when
بیان - توابع تک بیانی
- توابع و لامبداهای مرتبه بالاتر
- فیلترها
- دنباله ها
- نحو فراخوانی آخرین پارامتر
آموزش های کاتلین
وبسایت https://try.kotlinlang.org شامل آموزشهای غنی به نام Kotlin Koans، یک مترجم مبتنی بر وب و مجموعه کاملی از مستندات مرجع با مثال است.
دوره جسارت
برای مشاهده دوره Udacity در مورد این موضوع، به Kotlin Bootcamp for Programmers مراجعه کنید.
ایده IntelliJ
اسناد IntelliJ IDEA را می توان در وب سایت JetBrains یافت.
این بخش، تکالیف احتمالی را برای دانشآموزانی که در این آزمایشگاه کد به عنوان بخشی از دورهای که توسط یک مربی هدایت میشود، فهرست میکند. این وظیفه مربی است که موارد زیر را انجام دهد:
- در صورت نیاز تکالیف را تعیین کنید.
- نحوه ارسال تکالیف را با دانش آموزان در میان بگذارید.
- تکالیف را درجه بندی کنید.
مربیان میتوانند از این پیشنهادات به اندازهای که میخواهند استفاده کنند، و باید با خیال راحت هر تکلیف دیگری را که فکر میکنند مناسب است به آنها اختصاص دهند.
اگر به تنهایی بر روی این کدها کار می کنید، از این تکالیف برای آزمایش دانش خود استفاده کنید.
یه این سوالات پاسخ دهید
سوال 1
تابع contains(element: String)
در صورتی که element
رشته در رشته ای که روی آن فراخوانی می شود وجود داشته باشد، مقدار true
را برمی گرداند. خروجی کد زیر چه خواهد بود؟
val decorations = listOf ("rock", "pagoda", "plastic plant", "alligator", "flowerpot")
println(decorations.filter {it.contains('p')})
▢ [pagoda, plastic, plant]
▢ [pagoda, plastic plant]
▢ [pagoda, plastic plant, flowerpot]
▢ [rock, alligator]
سوال 2
در تعریف تابع زیر کدام یک از پارامترها مورد نیاز است؟
fun shouldChangeWater (day: String, temperature: Int = 22, dirty: Int = 20, numDecorations: Int = 0): Boolean {...}
▢ numDecorations
▢ dirty
▢ day
▢ temperature
سوال 3
می توانید یک تابع با نام معمولی (نه نتیجه فراخوانی آن) را به یک تابع دیگر منتقل کنید. چگونه increaseDirty( start: Int ) = start + 1
را به updateDirty(dirty: Int, operation: (Int) -> Int)
منتقل می کنید؟
▢ به روز رسانی updateDirty(15, &increaseDirty())
▢ به روز رسانی updateDirty(15, increaseDirty())
▢ به روز رسانی updateDirty(15, ("increaseDirty()"))
▢ به روز رسانی updateDirty(15, ::increaseDirty)
به درس بعدی بروید:
برای یک نمای کلی از دوره، از جمله پیوندهایی به دیگر کدها، به «کوتلین بوت کمپ برای برنامه نویسان: به دوره خوش آمدید» مراجعه کنید.