├── .gitignore ├── LICENSE ├── README.md └── src ├── README.md ├── a-brief-look-at-generics-in-kotlin-and-summary └── README.md ├── annotations-in-kotlin-and-summary └── README.md ├── classes-in-kotlin ├── README.md ├── result-1.PNG ├── result-2.PNG └── result-3.PNG ├── closures-in-kotlin └── README.md ├── conditional-execution-with-if-and-when-in-kotlin ├── README.md ├── result-1.PNG └── result-2.PNG ├── conventions-used-with-kotlin-and-summary └── README.md ├── declaring-constants └── README.md ├── declaring-variables-in-kotlin ├── README.md └── first-view-of-variables.PNG ├── deconstructing-values └── README.md ├── enum-classes-in-kotlin ├── README.md ├── result-1.PNG ├── result-2.PNG └── result-3.PNG ├── extension-functions-from-java └── README.md ├── extension-functions-in-kotlin-and-summary ├── README.md └── result-1.PNG ├── filtering-mapping-and-flatmapping-in-kotlin └── README.md ├── function-with-default-and-named-parameters-in-kotlin └── README.md ├── function-with-unlimited-parameters-in-kotlin-and-summary └── README.md ├── functions-in-kotlin └── README.md ├── higher-order-functions-in-kotlin ├── README.md └── result-1.PNG ├── inheritance-in-kotlin └── README.md ├── installing-the-tooling └── README.md ├── interfaces-in-kotlin ├── README.md └── result-1.PNG ├── interop-with-java-7-and-8-and-summary └── README.md ├── interoperability-with-java └── README.md ├── introduction-to-jvm └── README.md ├── kotlin-data-classes ├── README.md ├── result-1.PNG ├── result-2.PNG ├── result-3.PNG └── result-4.PNG ├── kotlin-standard-library-and-working-with-collections-in-kotlin ├── README.md ├── kotlin-collection.png ├── list-collection.png ├── listof-type.png └── listof.png ├── kotlin-with-intellij-idea ├── README.md ├── compiled-application.PNG ├── create-main.PNG ├── debug-application.PNG ├── new-project-1.PNG ├── new-project-2.PNG ├── new-project-3.PNG ├── view-of-first-application.PNG ├── view-of-main.PNG └── welcome-to-intellij-idea.PNG ├── lambda-expressions-in-kotlin ├── README.md └── result-1.PNG ├── loops-and-ranges-in-kotlin ├── README.md └── view-of-class.PNG ├── member-functions-in-kotlin └── README.md ├── null-safety-and-summary ├── README.md └── result-1.PNG ├── objects-in-kotlin-and-summary └── README.md ├── package-and-imports-in-kotlin-and-summary-of-kotlin-basic ├── README.md └── someutils.PNG ├── talking-to-java-from-kotlin └── README.md ├── talking-to-kotlin-from-java ├── README.md ├── completion-2.PNG ├── completion-3.PNG ├── error-1.PNG ├── warning-1.PNG └── warning-2.PNG ├── the-kotlin-repl ├── README.md ├── bye-repl.png ├── hello-fun.png ├── hello-world.png ├── kotlinc-command.png └── repl-in-idea.png ├── the-structure-of-kotlin-application └── README.md ├── top-level-functions-and-properties-in-kotlin ├── README.md ├── output-1.png └── output-2.png ├── tuples └── README.md ├── type-casting-in-kotlin ├── README.md └── result-1.PNG ├── typealias-in-kotlin └── README.md ├── visibility-modifiers-in-kotlin └── README.md ├── welcome-to-the-course └── README.md ├── why-kotlin └── README.md ├── working-with-abstract-classes-in-kotlin └── README.md ├── working-with-basic-types-in-kotlin └── README.md ├── working-with-exceptions ├── README.md ├── result-1.PNG └── result-2.PNG └── working-with-nulls-from-java └── README.md /.gitignore: -------------------------------------------------------------------------------- 1 | .idea -------------------------------------------------------------------------------- /LICENSE: -------------------------------------------------------------------------------- 1 | MIT License 2 | 3 | Copyright (c) 2018 Kotlin Farsi 4 | 5 | Permission is hereby granted, free of charge, to any person obtaining a copy 6 | of this software and associated documentation files (the "Software"), to deal 7 | in the Software without restriction, including without limitation the rights 8 | to use, copy, modify, merge, publish, distribute, sublicense, and/or sell 9 | copies of the Software, and to permit persons to whom the Software is 10 | furnished to do so, subject to the following conditions: 11 | 12 | The above copyright notice and this permission notice shall be included in all 13 | copies or substantial portions of the Software. 14 | 15 | THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR 16 | IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY, 17 | FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL THE 18 | AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER 19 | LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM, 20 | OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN THE 21 | SOFTWARE. 22 | -------------------------------------------------------------------------------- /README.md: -------------------------------------------------------------------------------- 1 | # OpenSourceTutorials-Introduction 2 | 3 | [![Join the chat at https://gitter.im/KotlinFarsi/OpenSourceTutorials-Introduction](https://badges.gitter.im/KotlinFarsi/OpenSourceTutorials-Introduction.svg)](https://gitter.im/KotlinFarsi/OpenSourceTutorials-Introduction?utm_source=badge&utm_medium=badge&utm_campaign=pr-badge&utm_content=badge) 4 | 5 | Pages of [Introduction to Kotlin Programming](https://kotlinfarsi.com/course/learning-kotlin-intro/) 6 | 7 | Kotlin 1.0 was released in February 2016, and since that time it’s been embraced by developers around the world, especially those within the Android community. This course provides an easy introduction to this open source programming language that covers the basics and showcases the language’s interoperability with Java and the JVM platform. A key feature of Kotlin is its similarity to Java, C#, and JavaScript. If you’re familiar with any of these languages, take this course and you’ll understand Kotlin on day one. 8 | 9 | This tutorial provided based on [O'Reilly Videos](http://shop.oreilly.com/product/0636920052982.do) 10 | 11 | Full course and another kotlin tutorials are accessible for free in KotlinFarsi.com website 12 | 13 | ## How to contribute on OpenSourceTutorials 14 | 15 | - install [git](https://git-scm.com/downloads) on your system 16 | - make a clone from this repo 17 | - make your changes 18 | - make a pull request 19 | 20 | ## How to be Writer on KotlinFarsi 21 | 22 | for being a writer or a teacher in KotlinFarsi website just ask me on twitter, and we will be happy to join our community 23 | -------------------------------------------------------------------------------- /src/README.md: -------------------------------------------------------------------------------- 1 |
2 | 3 | # فهرست 4 | 5 | **1 - مقدمه** 6 | 7 | [1.1 ) به دوره خوش آمدید](./welcome-to-the-course/README.md) 8 | 9 | [1.2 ) چرا کاتلین؟](./why-kotlin/README.md) 10 | 11 | **2 - مبانی کاتلین** 12 | 13 | [2.1 ) آشنایی با JVM](./introduction-to-jvm/README.md) 14 | 15 | [2.2 ) نصب کردن ابزارآلات](./installing-the-tooling/README.md) 16 | 17 | [2.3 ) کاتلین REPL](./the-kotlin-repl/README.md) 18 | 19 | [2.4 ) ساختار یک برنامه کاتلین](./the-structure-of-kotlin-application/README.md) 20 | 21 | [2.5 ) کاتلین با IntelliJ IDEA](./kotlin-with-intellij-idea/README.md) 22 | 23 | [2.6 ) خلاصه بخش دوم](./conventions-used-with-kotlin-and-summary/README.md) 24 | 25 | **3 - کد نویسی مقدماتی کاتلین** 26 | 27 | [3.1 ) تعریف متغیر در کاتلین](./declaring-variables-in-kotlin/README.md) 28 | 29 | [3.2 ) کار با Type های پایه ای](./working-with-basic-types-in-kotlin/README.md) 30 | 31 | [3.3 ) حلقه ها در کاتلین](./loops-and-ranges-in-kotlin/README.md) 32 | 33 | [3.4 ) عبارت های شرطی در کاتلین](./conditional-execution-with-if-and-when-in-kotlin/README.md) 34 | 35 | [3.5 ) اضافه کردن پگیج ها در کاتلین و خلاصه بخض سوم](./package-and-imports-in-kotlin-and-summary-of-kotlin-basic/README.md) 36 | 37 | **4 - توابع** 38 | 39 | [4.1 ) توابع در کاتلین](./functions-in-kotlin/README.md) 40 | 41 | [4.2 ) تابع با پارامترهای پیشفرض و نامیده شده](./function-with-default-and-named-parameters-in-kotlin/README.md) 42 | 43 | [4.3 ) تابع با پرامترهای نامحدود و خلاصه بخش چهارم](./function-with-unlimited-parameters-in-kotlin-and-summary/README.md) 44 | 45 | **5 - کلاس ها** 46 | 47 | [5.1 ) کلاس ها در کاتلین](./classes-in-kotlin/README.md) 48 | 49 | [5.2 ) توابعِ عضو در کاتلین](./member-functions-in-kotlin/README.md) 50 | 51 | [5.3 ) visibility modifier ها در کاتلین](./visibility-modifiers-in-kotlin/README.md) 52 | 53 | [5.4 ) کلاس های دیتا در کاتلین](./kotlin-data-classes/README.md) 54 | 55 | [5.5 ) کلاس های enum در کاتلین](./enum-classes-in-kotlin/README.md) 56 | 57 | [5.6 ) Object ها در کاتلین و خلاصه بخش پنج](./objects-in-kotlin-and-summary/README.md) 58 | 59 | **6 - ارث بری** 60 | 61 | [6.1 ) ارث بری در کاتلین](./inheritance-in-kotlin/README.md) 62 | 63 | [6.2 ) کارکردن با کلاس های abstract در کاتلین](./working-with-abstract-classes-in-kotlin/README.md) 64 | 65 | [6.3 ) کلاس های interface در کاتلین](./interfaces-in-kotlin/README.md) 66 | 67 | [6.4 ) نگاه کوتاه به generic ها و خلاصه بخش شش](./a-brief-look-at-generics-in-kotlin-and-summary/README.md) 68 | 69 | **7 - کارکردن با Null ها** 70 | 71 | [7.1 ) null safety و خلاصه بخش هفت](./null-safety-and-summary/README.md) 72 | 73 | **8 - نکات اضافه** 74 | 75 | [8.1 ) type casting در کاتلین](./type-casting-in-kotlin/README.md) 76 | 77 | [8.2 ) چندتایی ها (Tuples)](./tuples/README.md) 78 | 79 | [8.3 ) deconstructing values](./deconstructing-values/README.md) 80 | 81 | [8.4 ) کار کردن با exception ها](./working-with-exceptions/README.md) 82 | 83 | [8.5 ) constant ها](./declaring-constants/README.md) 84 | 85 | [8.6 ) typealias ها](./typealias-in-kotlin/README.md) 86 | 87 | [8.7 ) annotation ها در کاتلین و خلاصه بخش هشت](./annotations-in-kotlin-and-summary/README.md) 88 | 89 | **9 - نگاه functionalای** 90 | 91 | [9.1 ) توابع Higher-Order](./higher-order-functions-in-kotlin/README.md) 92 | 93 | [9.2 ) عبارت های لاندا در کاتلین](./lambda-expressions-in-kotlin/README.md) 94 | 95 | [9.3 ) closure ها در کاتلین](./closures-in-kotlin/README.md) 96 | 97 | [9.4 ) عبارت های الحاقی در کاتلین و خلاصه بخش نهم](./extension-functions-in-kotlin-and-summary/README.md) 98 | 99 | **10 - قابلیت همکاری و Interoperability** 100 | 101 | [10.1 ) همکاری با جاوا](./interoperability-with-java/README.md) 102 | 103 | [10.2 ) صحبت کردن با جاوا از کاتلین](./talking-to-java-from-kotlin/README.md) 104 | 105 | [10.3 ) کار کردن با null ها از جاوا](./working-with-nulls-from-java/README.md) 106 | 107 | [10.4 ) صحبت کردن با کاتلین از جاوا](./talking-to-kotlin-from-java/README.md) 108 | 109 | [10.5 ) توابع و خصیصه های درجه اول](./top-level-functions-and-properties-in-kotlin/README.md) 110 | 111 | [10.6 ) توابع الحاقی کاتلین از جاوا](./extension-functions-from-java/README.md) 112 | 113 | [10.7 ) همکاری با جاوا 7 و 8 و خلاصه بخش دهم](./interop-with-java-7-and-8-and-summary/README.md) 114 | 115 | **11 - کتابخانه استاندارد** 116 | 117 | [11.1 ) کتابخانه استاندارد کاتلین و کارکردن با کالکشن ها در کاتلین](./kotlin-standard-library-and-working-with-collections-in-kotlin/README.md) 118 | 119 | [11.2 ) مرور کوتاه بر روی filtering و mapping و flatmapping در کاتلین](./filtering-mapping-and-flatmapping-in-kotlin/README.md) 120 | 121 | -------------------------------------------------------------------------------- /src/a-brief-look-at-generics-in-kotlin-and-summary/README.md: -------------------------------------------------------------------------------- 1 |
2 | 3 | # نگاه کوتاه به generic ها و خلاصه بخش شش 4 | 5 | حالا فرض کنید من یک اینتفریس دارم به نام EmployeeRepository و این کد هارو براش زدم 6 | 7 |
8 | 9 | ```kotlin 10 | class Employee 11 | 12 | interface EmployeeRepository{ 13 | fun store(onj: Employee){ 14 | 15 | } 16 | fun getById(id : Int) : Employee 17 | } 18 | ``` 19 | 20 |
21 | 22 | میبینین که ما درواقع یک سری کد رو تکرار کردیم. کلاس CustomerRepository (که جلسه قبل نوشتیم) و کلاس EmployeeRepository مون، دوتابع تکراری store و getById دارن و تنها تفاوت بین این دو تایپی که توابعش بر میگردونن است ، یکی Employee و یکی دیگه Customer.حالا اگه شما با برنامه نویسی اشنا باشین میدونین که چجوری بتونیم به مقصود دلخواهمون برسیم و اون هم استفاده از Generic هاست. بذارین شیوه کارمون رو توضیح بدم، ما یک سری کلاس های Generics تولید میکنیم که قراره یک سری پارامتر به نامType Parameter رو بگیرن و محصولی رو تولید کنن.خب پس بیاین ببینیم چجوری این کار انجام میشه. 23 | 24 |
25 | 26 | ```kotlin 27 | interface Repository { 28 | fun getById(id:Int) : T 29 | 30 | fun getAll() : List 31 | } 32 | ``` 33 | 34 |
35 | 36 | یک اینترفیس ساختیم به نام Repository که یک Type Parameter میگیره به نام T و دو تابع هم داریم که یکی اون پارامتر رو با یک شماره برمیگردونه و یکی دیگه هم لیست کل پارامتر هارو برمیگردونه. 37 | 38 | نحوه استفاده ازش هم راحته، کافیه یک کلاس بسازیم به نام CustomerGenericRepository به فرم زیر 39 | 40 |
41 | 42 | ```kotlin 43 | class Customer 44 | 45 | interface Repository { 46 | fun getById(id:Int) : T 47 | 48 | fun getAll() : List 49 | } 50 | 51 | class CustomerGenericRepository : Repository { 52 | override fun getById(id: Int): T { 53 | TODO("not implemented") 54 | } 55 | 56 | override fun getAll(): List { 57 | TODO("not implemented") 58 | } 59 | } 60 | 61 | fun main(args: Array) { 62 | val customerRepo = CustomerGenericRepository() 63 | } 64 | ``` 65 | 66 |
67 | 68 | حالا شما تقریبا متوجه شدین که Customerهه اول نام CustomerGenericRepository درواقع اضافه است! چون لازم نیست که لغت Customer رو اولش بیاریم. تنها کاری که باید انجام بدیم اینه که یک کلاس بسازیم به نام GenericRepository و بعدش Employee و Customer رو بهش پاس بدیم!خب پس میریم و Customer رو از اولش بر میداریم. 69 | 70 |
71 | 72 | ```kotlin 73 | class Customer 74 | class Employee 75 | 76 | interface Repository { 77 | fun getById(id:Int) : T 78 | 79 | fun getAll() : List 80 | } 81 | 82 | class GenericRepository : Repository { 83 | override fun getById(id: Int): T { 84 | TODO("not implemented") 85 | } 86 | 87 | override fun getAll(): List { 88 | TODO("not implemented") 89 | } 90 | } 91 | fun main(args: Array) { 92 | val customerRepo = GenericRepository() 93 | val employeeRepo = GenericRepository() 94 | } 95 | ``` 96 | 97 |
98 | 99 | همچنین ما میتونیم Generic هارو برای توابع هم استفاده کنیم 100 | 101 |
102 | 103 | ```kotlin 104 | interface Repo{ 105 | fun getById(id : Int) : T 106 | fun getAll() : List 107 | } 108 | 109 | class MyRepo : Repo { 110 | override fun getById(id: Int): T { 111 | TODO("not implemented") 112 | } 113 | 114 | override fun getAll(): List { 115 | TODO("not implemented") 116 | } 117 | } 118 | ``` 119 | 120 | 121 |
122 | 123 | البته زمانی که کل کلاس از یک تایپ استفاده میکنن، خب بهتره که کل کلاس رو Type Parameter بدیم تا این که تک تک توابع رو، ولی زمانی که توابع داخل کلاس، هر کدوم Type Parameter های متفاوت میگیرن اون موقع این کار منطقیه. 124 | 125 | **خلاصه بخش 6:** 126 | 127 | 1- به صورت پیش فرض تموم کلاس ها final هستند، در هنگام ارث بری نیاز به کلید واژه open داریم 128 | 129 | 2- کلاس های abstract به مانند interface هستند با این تفاوت که اجازه میدن حالت رو نگه داریم 130 | 131 | 3- کاتلین هم همچنین اجازه میده تا کلاس و متد های Generic داشته باشیم و البته در دوره Advance بیشتر به این مورد ها میپردازیم. 132 | 133 | 134 |
135 | 136 | -------------------------------------------------------------------------------- /src/annotations-in-kotlin-and-summary/README.md: -------------------------------------------------------------------------------- 1 |
2 | 3 | # annotation ها در کاتلین و خلاصه بخش هشت 4 | 5 | درواقع Annotation های کاتلین کاملا با Annotation های جاوا همسو هستن. در قسمت Advance میبینیم که چه طور Annotation های دلخواه خودمون رو درست کنیم ولی فعلا یادتون میدم که چجوری بتونین از Annotation های آماده ی جاوا استفاده کنید. 6 | 7 | برای یادگیری این مبحث لازمه که حداقل با Junit اشنا باشین و Junit رو به پروژتون اضافه کنین 8 | 9 |
10 | 11 | ```kotlin 12 | import org.junit.Test 13 | 14 | class AnnotationsTest{ 15 | @Test fun testAnnotation(){ 16 | 17 | } 18 | } 19 | ``` 20 | 21 |
22 | 23 | دقیقا به همون طریقی که Annotation هارو توی جاوا استفاده میکردیم اینجا هم با قراردادن @ میتونیم از اون ها استفاده کنیم. 24 | 25 | همینطور که کلاس هارو میتونیستم با استفاده از as با نام دیگه صدا بزنیم اینجاهم میتونیم همین کار رو انجام بدیم 26 | 27 |
28 | 29 | ```kotlin 30 | import org.junit.Test as Specification 31 | 32 | class AnnotationsTest{ 33 | @Specification fun testAnnotation(){ 34 | 35 | } 36 | } 37 | ``` 38 | 39 |
40 | 41 | **خلاصه بخش 8:** 42 | 43 | 1- با SmartCasting اشنا شدیم 44 | 45 | 2- فهمیدم که چندگانه ها در کاتلین محدود هستند، بیشتر از 3گانه باید از کلاس های دیتا استفاده بشه 46 | 47 | 3- یادگرفتیم چگونه یک مقدار رو بشکنیم و این زمانیکه میخوایم از کلاس های دیتا یا چندگانه ها استفاده کنیم مفیده و معنی بهتری داره 48 | 49 | 4- نیازی به Exception های چک شده در کاتلین وجود ندارند. 50 | 51 | 5- Constant ها میتونند یا به صورت objectو یا به عنوان خصیصه های Top-Level استفاده بشن 52 | 53 | 6- Annotation ها در کاتلین قابل دسترسی اند و همچنین Annotation های جاوا رو میشه در کاتلین استفاده کرد 54 | 55 | 56 |
57 | -------------------------------------------------------------------------------- /src/classes-in-kotlin/README.md: -------------------------------------------------------------------------------- 1 |
2 | 3 | # کلاس ها در کاتلین 4 | 5 | برای تعریف یک کلاس به همین سادگی نوشتن خط کد زیر کافی است 6 | 7 |
8 | 9 | ```kotlin 10 | class Customer 11 | ``` 12 | 13 |
14 | 15 | من درواقع هیچ گونه نیازی به باز کردن یا بستن آکولاد یا هر کاری شبیه این ها ندارم.تنها کلیدواژه class و بعد ان نام class . 16 | 17 | خب به هر حال کلاسمون نمیشه انقدر ساده باشه، کلاسمون باید مثل زبون های دیگه property یا خاصیت داشته باشه. اگه بخوام property داشته باشم باید اکولاد رو باز و بسته کنم. البته که تعریف یک خاصیت خیلی سادس، به راحتی خط زیر 18 | 19 |
20 | 21 | ```kotlin 22 | class Customer{ 23 | var id = 0 24 | } 25 | ``` 26 | 27 |
28 | 29 | اگه دقت کنیم متوجه میشیم که تعریف خاصیت دقیقا به مانند تعریف متغیرهاست و به مانند متغیر ها لازم نیست که صریحا بیان کنم که چه نوع متغییر میخوام و میتونم تایپش رو مشخص نکنم. اگه بخوام این کارو انجام بدم به همین راحتی میتونم بیانش کنم 30 | 31 |
32 | 33 | 34 | ```kotlin 35 | var name : String = "" 36 | ``` 37 | 38 |
39 | 40 | یکی از ویژگی های کاتلین که این زبون رو متفاوت از زبون دیگه میکنه اینه که مفهومی به نام field در این زبون وجود نداره پس هرچیزی که بعد تعریف کلاس معرفی میشه همون خاصیت ها یا property هان. همینطور به مانند متغیر ها ما میتونیم متغیر غیرقابل تغییر بسازیم، همونایی که با کلید واژه val مشخص میشدند. 41 | 42 | حالا اگه من بخوام از این کلاس استفاده کنم 43 | 44 |
45 | 46 | ```kotlin 47 | class Customer{ 48 | var id = 0 49 | var name : String = "" 50 | } 51 | 52 | fun main(args: Array) { 53 | var customer = Customer() 54 | } 55 | ``` 56 | 57 |
58 | 59 | به همین راحتی، اگه توجه کنین کلیدواژه new که قبلا در جاوا استفاده میشد اینجا نیست. درواقع نیازی به new در اینجا نداریم. برای دسترسی به خاصیت ها 60 | 61 |
62 | 63 | ```kotlin 64 | customer.id = 10 65 | customer.name = "Sina" 66 | ``` 67 | 68 |
69 | 70 | تنها کاری که باید بکنیم استفاده از "." است. 71 | 72 | ولی اگه نگاه کنید من اومدم و خاصیت هارو مقدار دهی کردم، ولی اگر بخوام خاصیت هام مقدار دهی نشده باشند چی ؟ درواقع مسلما من زمانی میخوام مقدار دهی اولیه نکنم که اون ها مثلا توی سازنده ( Constructor ) مقدار دهی بشن. 73 | 74 | خب اول بیام مقدار اولیه خاصیت هارو حذف کنم. 75 | 76 |
77 | 78 | ```kotlin 79 | class Customer{ 80 | var id : Int 81 | var name : String 82 | } 83 | ``` 84 | 85 |
86 | 87 | همینطور که میبینین، متوجه خواهید شد که کامپایلر ارور میده و میگه این خاصیت ها مقدار دهی نشده اند.در کاتلین شما میتونین این کار رو به این روش سنتی انجام بدین 88 | 89 |
90 | 91 | ```kotlin 92 | class Customer(initId : Int, initName: String){ 93 | var id : Int = initId 94 | var name : String = initName 95 | } 96 | ``` 97 | 98 |
99 | 100 | ولی خب کدزنیمون زیاد شد.دوتا متغییر گرفتیم و اون هارو موقعی که میخوایم از این کلاس شی بسازیم مقدار دهی میکنیم و بعد کلاس میاد این هارو به خاصیت ها پاس میده.یکم زیاده. 101 | 102 | خب من میتونم به یک روش دیگه هم خاصیت هامو تعریف کنم 103 | 104 |
105 | 106 | ```kotlin 107 | class Customer(var id : Int, var name: String){ 108 | } 109 | 110 | ``` 111 | 112 |
113 | 114 | این یعنی این که من زمانی که با کانستراکتور شی ام رو میسازم مقادیر property هامو هم به کلاس پاس میدم. 115 | 116 | توجه کنین که اگه var یا val اول متغیر ها توی کانستراکتور نمی آمد در واقع این دو فقط و فقط دو مقدار بودند که به کانستراکتور پاس داده شده اند و نمیتوانستیم بعدا با استفاده “.” از اون ها استفاده کنیم. 117 | 118 | همینطور که برای توابع مقادیر پیشفرض استفاده میشد برای کلاس ها هم مقادیر پیشفرض استفاده میشه، من میتونم کلاس زیر رو بسازم 119 | 120 |
121 | 122 | ```kotlin 123 | class Customer(var id : Int, var name: String = "") 124 | ``` 125 | 126 |
127 | 128 | ولی یادتون باشه که خاصیتمون باید تایپ داشته باشه، نمیتونیم بنویسیم 129 | 130 |
131 | 132 | ```kotlin 133 | class Customer(var id : Int, var name = "") //Wrong 134 | ``` 135 | 136 |
137 | 138 | بیاین یکم بیشتر جلوبریم، اگه فرض کنین من بخوام name رو به حروف بزرگ(UpperCase) تبدیل کنم.کاری که میکنیم اینه که از بلاک init استفاده میکنیم.در واقع init مخفف Initialization هستش، بدین معنی که همون اول که یک کلاس ساخته میشه این بلاک اجرا میشه.مثلا قطعه کد زیر رو در نظر بگیرین 139 | 140 |
141 | 142 | ```kotlin 143 | class Customer(var id : Int, var name: String = ""){ 144 | init { 145 | name.toUpperCase() 146 | } 147 | } 148 | 149 | fun main(args: Array) { 150 | var customer = Customer(10,"sina") 151 | println(customer.name) 152 | } 153 | ``` 154 | 155 |
156 | 157 | حالا اگه این کد رو اجرا کنیم نتیجه زیر رو میبینیم 158 | 159 | 160 | 161 | خب اگه دقت کنین ما اومدین و تابع `toUpperCase()` روی `name` پیاده کردیم ولی مقدار جدید رو توی `name` نریختیم. برای این که این مشکل رو حل کنیم میتونیم این کار رو انجام بدیم 162 | 163 |
164 | 165 | ```kotlin 166 | name = name.toUpperCase() 167 | ``` 168 | 169 |
170 | 171 | چون در غیر این صورت تنها اون تابع رو اجرا کردیم و اون رو برنگردوندیم. 172 | 173 | ما دیدیم که میتونیم یک کانستراکتور داشته بایم که مقادیر پیشفرض داشته باشه، ولی گاهی اوقات میشه که لازم بشه که بخوایم چند کانستراکتور داشته باشیم ، مثلا قطعه کد زیر رو در نظر بگیرید 174 | 175 |
176 | 177 | ```kotlin 178 | class Customer(var id : Int, var name: String = ""){ 179 | init { 180 | name = name.toUpperCase() 181 | } 182 | 183 | constructor(email: String): this(0,""){ 184 | 185 | } 186 | } 187 | ``` 188 | 189 |
190 | 191 | در واقع اومدیم و یک کانستراکتور دوم ساختیم که خاصیت های ان همان id و name با مقادیر به ترتیب 0 و “” هستند ولی یک متغییر به نام email هم داریم.توجه کنین که اکولاد جلوی کانستراکتور دوم به مانند init هست، یعنی هر کاری که جلوی اون بیاد در همون اول برنامه انجام داده میشه. 192 | 193 | اگه از جاوا یادتون باشه ما میتونیم برای مقدار دهی و یا گرفتن مقادیر از getter و setter استفاده کنیم. کاتلین این اجازه رو بهمون میده که ما بتونیم getter و setter دلخواه خودمون رو بنویسیم 194 | 195 |
196 | 197 | ```kotlin 198 | class Customer(var id: Int, var name: String, var yearOfBirth: Int){ 199 | val age :Int 200 | get() = Calendar.getInstance().get(Calendar.YEAR) - yearOfBirth 201 | } 202 | ``` 203 | 204 |
205 | 206 | در واقع ما اومدیم و یک getter کاستوم برای یک خاصیتمون نوشتیم. 207 | 208 | همونطور که ما یک getter دلخواه داشتیم میتونیم setter دلخواهم داشته باشیم. 209 | 210 |
211 | 212 | ```kotlin 213 | class Customer(var id: Int, var name: String, var yearOfBirth: Int){ 214 | val age :Int 215 | get() = Calendar.getInstance().get(Calendar.YEAR) - yearOfBirth 216 | 217 | var socialSecurityNumber: String = "" 218 | set(value) { 219 | if(!value.startsWith("SM")){ 220 | throw IllegalArgumentException("Social security should start with SM") 221 | } 222 | } 223 | } 224 | ``` 225 | 226 |
227 | 228 | اگه کد بالا رو خونده باشین متوجه میشین که ما اگر مقداری به socialSecrityNumber بدیم که با “SM”شروع نشه یک exception برمیگردونه. 229 | 230 | خب بیاین تست کنیم 231 | 232 |
233 | 234 | ```kotlin 235 | fun main(args: Array) { 236 | var customer = Customer(10, "Sina",1995) 237 | println(customer.age) 238 | 239 | customer.socialSecurityNumber = "11234" 240 | } 241 | ``` 242 | 243 |
244 | 245 | اگه این کد رو اجرا کنیم نتیجه زیر رو خواهیم داشت 246 | 247 | 248 | 249 | خب مسلما اگه socialSecurityNumber رو تغییر بدیم و سعی کنیم اونو چاپ کنیم 250 | 251 |
252 | 253 | ```kotlin 254 | fun main(args: Array) { 255 | var customer = Customer(10, "Sina",1995) 256 | customer.socialSecurityNumber = "SM11234" 257 | 258 | println(customer.age) 259 | println(customer.socialSecurityNumber) 260 | } 261 | ``` 262 | 263 |
264 | 265 | نتیجه زیر رو خواهیم داشت 266 | 267 | 268 | 269 | متوجه میشیم که اون مشکل مربوط به Exception رفع شد ولی مقدارش چاپ نشد.خب البته اگه دقت کنین ما اومدیم و محدودیت گذاشتیم براش ولی نگفتین این مقدار رو بگیره. برای این که بتونیم مقدار رو بهش بدیم از کلیدواژه ای به نام field استفاده میکنیم. 270 | 271 |
272 | 273 | ```kotlin 274 | class Customer(var id: Int, var name: String, var yearOfBirth: Int){ 275 | val age :Int 276 | get() = Calendar.getInstance().get(Calendar.YEAR) - yearOfBirth 277 | 278 | var socialSecurityNumber: String = "" 279 | set(value) { 280 | if(!value.startsWith("SM")){ 281 | throw IllegalArgumentException("Social security should start with SM") 282 | } 283 | field = value 284 | } 285 | } 286 | ``` 287 | -------------------------------------------------------------------------------- /src/classes-in-kotlin/result-1.PNG: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/KotlinFarsi/OpenSourceTutorials-Introduction/92e9b633b82753deae74fa498e634a58c863e1d0/src/classes-in-kotlin/result-1.PNG -------------------------------------------------------------------------------- /src/classes-in-kotlin/result-2.PNG: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/KotlinFarsi/OpenSourceTutorials-Introduction/92e9b633b82753deae74fa498e634a58c863e1d0/src/classes-in-kotlin/result-2.PNG -------------------------------------------------------------------------------- /src/classes-in-kotlin/result-3.PNG: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/KotlinFarsi/OpenSourceTutorials-Introduction/92e9b633b82753deae74fa498e634a58c863e1d0/src/classes-in-kotlin/result-3.PNG -------------------------------------------------------------------------------- /src/closures-in-kotlin/README.md: -------------------------------------------------------------------------------- 1 |
2 | 3 | # closure ها در کاتلین 4 | 5 | خب حالا که با چند تا از ویژگی های Lambda آشنا شدین خوبه که سراغ بحث دیگه ای به نام Closure ها بریم: 6 | 7 |
8 | 9 | ```kotlin 10 | fun unaryOperation(x:Int,op: (Int) -> Int){ 11 | op(x) 12 | } 13 | fun outsideFunction() { 14 | val number = 10 15 | unaryOperation(20) { it * number } 16 | } 17 | ``` 18 | 19 |
20 | 21 | یک تابع نوشتیم که یک تابع High-Order داخلش استفاده شده. (همون unaryOperation که توی جلسه قبلی ساختیمش) و دیدین که این تابع High-Order به متغیر خارج عبارت لاندایی که تعریف کردیم دسترسی داره! و اگه با IntelliJ IDEA این کد رو بزنین متوجه میشین که با نگه داشتن موشواره بر روی number بهمون میگه که “variable captured in a closure” و درواقع این بهمون میفهمونه که ما به مقدار متغییری دسترسی داشتیم که خارج عبارت lambda تعریف شده و مشکلی هم نداره. 22 | 23 | بذارین یه حلقه for داشته باشیم 24 | 25 |
26 | 27 | ```kotlin 28 | fun unaryOperation(x:Int,op: (Int) -> Int){ 29 | op(x) 30 | } 31 | fun outsideFunction() { 32 | for (number in 1..30) { 33 | unaryOperation(20) { 34 | println(number) 35 | it * number 36 | } 37 | } 38 | } 39 | 40 | fun main(args: Array){ 41 | outsideFunction() 42 | } 43 | ``` 44 | 45 |
46 | 47 | که بیاد و در هر مرتبه اجرا مقدار number رو پرینت کنه. اگه توی main تابع outsideFunction رو صدا بزنیم متوجه میشیم که مقادیر تغییر میکنن و لازم به گفتنه که در بعضی زبان‌ها اینجوری تعریف شدن که مقدار متغییرها ثابت بمونن ولی در کاتلین میتونن تغییر کنند. 48 | 49 |
50 | -------------------------------------------------------------------------------- /src/conditional-execution-with-if-and-when-in-kotlin/README.md: -------------------------------------------------------------------------------- 1 |
2 | 3 | # عبارت های شرطی در کاتلین 4 | 5 | مثل بقیه زبان های برنامه نویسی کاتلین هم از عبارات شرطی نیز استفاده میکنه ولی با مقداری تفاوت که در ادامه میبینیم: 6 | 7 |
8 | 9 | ```kotlin 10 | var myString= "Not Empty" 11 | if(myString != ""){ 12 | println("Not Empty") 13 | }else if (myString.startsWith("a")){ 14 | println("Starts With A") 15 | }else{ 16 | println("Is Empty") 17 | } 18 | ``` 19 | 20 |
21 | 22 | خب تا اینجا که مثل بقیه زبون ها عمل کردیم، ولی یکی از ویژگی های کاتلین اینه که میتونه به عنوان یک عبارت بیان بشه، قطعه کد زیر رو نگاه کنید: 23 | 24 |
25 | 26 | ```kotlin 27 | var result = if(myString != ""){ 28 | println("Not Empty") 29 | }else { 30 | println("Starts With A") 31 | } 32 | 33 | println(result) 34 | ``` 35 | 36 |
37 | 38 | اگر این رو اجرا کنیم برنامه خروجی زیر رو میده 39 | 40 | 41 | 42 | چرا kotlin.Unit ؟ درواقع Unit د رکاتلین به مانند void میمونه. ولی من گفتم که کاتلین این اجازه رو میده که بتونیم از if به صورت یک عبارت شرطی استفاده کنیم، خب باید توجه کنیم که اگر if بدین صورت استفاده بشه، کاتلین اخرین خط رو به عنوان مقدار برمیگردونه، یعنی اگر بخواهم به هدف دلخواهمون برسیم باید کد رو به صورت زیر تغییر بدیم: 43 | 44 |
45 | 46 | ```kotlin 47 | var result = if(myString != ""){ 48 | "Not Empty" 49 | }else { 50 | "Starts With A" 51 | } 52 | 53 | println(result) 54 | ``` 55 |
56 | 57 | توجه کنین که مقدار اخرین خط بازگردادنده بشه، پس اگر بعد از “Not Empty” مقدار 20 گذاشته شود، جواب 20 برگردانده میشود. 58 | 59 | بیاین یک نکته دیگه رو هم بگم. اگه عبارت بالا رو به این صورت بنویسم 60 | 61 |
62 | 63 | ```kotlin 64 | var result = if(myString != ""){ 65 | 20 66 | }else { 67 | "Starts With A" 68 | } 69 | println(result) 70 | ``` 71 | 72 |
73 | 74 | 75 | متوجه میشیم که کاپایلر یک اخطار میده و میگه result رو به Any کست میکنه!! در واقع Any یک کلاس بالایی است که دیگر شی ها از اون ارث بری شدند( اگر با مفهوم ارث بری اشنا نیستید، بعدا در مورد اون ها صحبت خواهیم کرد) و در واقع این اخطار به ما اینو میگه : " ایا خبر داری که این عبارت شرطیت یک جا Int بر میگردونه و یک جای دیگه String ؟" 76 | 77 | نکته دیگه باید توجه کنید اینه که وقتی داریم مقدار یک if رو به یک متغیر نسبت میدیم حتما باید برای تمامی شرایط مقداری برگردونیم.مثلا اگر به صورت زیر بنویسیم 78 | 79 |
80 | 81 | ```kotlin 82 | var result = if(myString != ""){ 83 | 20 84 | } 85 | println(result) 86 | ``` 87 | 88 |
89 | 90 | متوجه میشیم که برناممون با ارور مواجه میشه، و اونم دلیلش اینه که کامپایلر نمیدونه که اگر مثلا myString ==”” بود چه عملی رو انجام بده. 91 | 92 | همانند if ما یک عبارت دیگه داریم به نام when که تقریبا به مانند case در زبون های دیگه میمونه. 93 | 94 |
95 | 96 | ```kotlin 97 | var result = "Value" 98 | when(result){ 99 | is String -> println("Excellent") 100 | "Value" -> println("It's a Value") 101 | } 102 | ``` 103 | 104 |
105 | 106 | مثلا عبارت بالا زو مد نظر بگیرین، اومدم نوشتم اگه result یک String بود عبارت اول رو چاپ کنه و اگر برابر بود با “Value” عبارت دوم رو. خب به نظرتون اگه این کد رو اجرا کنم خروجی چی میشه ؟ 107 | 108 | 109 | 110 | 111 | همینطور که میبینین عبارت “Excellent” چاپ شد. در واقع وقتی در داخل when به یکی از جواب ها برسیم کامپایلر دیگه خط های پایین رو نگاه نمیکنه و سریع break میکنه. 112 | 113 | همانند if ، when هم میتونه عبارت شرطی باشه و نتیجش رو به یک متغییر پاس بدیم. 114 | 115 | 116 |
117 | 118 | ```kotlin 119 | var result = "Value" 120 | val whenValue = when(result){ 121 | "Value" -> { 122 | println("It's a Value") 123 | println("Second statement") 124 | } 125 | is String -> println("Excellent") 126 | } 127 | println(whenValue) 128 | ``` 129 | 130 |
131 | 132 | عبارت بالا رو مینویسیم، دقیقا به مانند if ، ولی وقتی این کد ر اجرا میکنیم با ارور مواجه میشیم. اینجا هم مثل if کامپایلر برمیگرده میگه " من میدونم اگه برابر “Value” بود چیکار کنم، میدونم اگه String بود چیکار کنم ولی اگه توی وضعیت دیگه ای بود چیکار کنم ؟ مشکل را با استفاده از کلید واژه else رفع میکنم، بدین صورت 133 | 134 |
135 | 136 | ```kotlin 137 | var result = "Value" 138 | val whenValue = when(result){ 139 | "Value" -> { 140 | println("It's a Value") 141 | println("Second statement") 142 | } 143 | is String -> println("Excellent") 144 | else -> println("It came to this?") 145 | } 146 | println(whenValue) 147 | ``` 148 | 149 |
150 | 151 | البته همینطور ک متوجه شدین، اگر این برنامه رو اجرا کنیم مقدار Unit برگردانده میشود و دلیل ان هم واضح است چرا که ما هنوز چیزی در اخرین خط شرط هامون برنگردوندیم! 152 | 153 |
154 | 155 | ```kotlin 156 | var result = "Value" 157 | val whenValue = when(result){ 158 | "Value" -> { 159 | println("It's a Value") 160 | println("Second statement") 161 | "Here" 162 | } 163 | is String -> { 164 | println("Excellent") 165 | "And Here" 166 | } 167 | else -> { 168 | println("It came to this?") 169 | "and what about here?" 170 | } 171 | } 172 | println(whenValue) 173 | ``` 174 | -------------------------------------------------------------------------------- /src/conditional-execution-with-if-and-when-in-kotlin/result-1.PNG: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/KotlinFarsi/OpenSourceTutorials-Introduction/92e9b633b82753deae74fa498e634a58c863e1d0/src/conditional-execution-with-if-and-when-in-kotlin/result-1.PNG -------------------------------------------------------------------------------- /src/conditional-execution-with-if-and-when-in-kotlin/result-2.PNG: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/KotlinFarsi/OpenSourceTutorials-Introduction/92e9b633b82753deae74fa498e634a58c863e1d0/src/conditional-execution-with-if-and-when-in-kotlin/result-2.PNG -------------------------------------------------------------------------------- /src/conventions-used-with-kotlin-and-summary/README.md: -------------------------------------------------------------------------------- 1 |
2 | 3 | # خلاصه بخش دوم 4 | 5 | خب ما توی این دوره قراره که کلی کد کاتلین بزنیم، بنابر این بهتره که با یک سری قرارداد های اون آشنا بشیم. کاتلین تمرکز اصلیش روی Java بوده بنابراین ما همون قرارداد های جاوا رو دنبال میکنیم بنابراین اگر با قرارداد های جاوا آشنا نیستید بهتره که همین الان با هم یک مروری بکنیم. ما از LowerCamelCase ها برای نامگذاری استفاده می کنیم، این به این معنیه : 6 | 7 |
8 | 9 | ```kotlin 10 | var HelloWorld // eshtebah 11 | var helloWorld // dorost 12 | ``` 13 | 14 |
15 | 16 | تایپ ها(Types) رو با حروف درشت مینویسیم، متد ها و خاصیت هارو با lower camelcase مینویسیم ، نقطه ویزگول ها اختیاری هستند و تنها یک جا ازشون استفاده میشه( بعدا راجع بهش صحبت میکنیم) ، پکیج ها برعکس نوشته میشوند یعنی به جای introduction.kotlinfarsi.com مینویسیم com.kotlinfarsi.introduction 17 | 18 | شما میتونید چندی کلاس در یک فایل داشته باشید و همچنین پکیج ها نیاز ندارند که دقیقا هم نام فولدر ها باشند هرچند که این پیشنهاد میشوند. 19 | 20 | ## خلاصه این بخش: 21 | 22 | 1- کاتلین زبونیه که Java و هم JavaScript رو هم پوشش میده ( البته روی ورژنی از کاتلین داره کار میشه به نام Kotlin Native که اون دیگه اوج برنامه نویسیه و یک دوره مجزا نیاز داره تا بشه توضیح بدیم، این بخش درحال توسعه است) 23 | 24 | 2- کاتلین بایت کد هایی رو درست میکنه که با JVM قابل اجرا هستش. 25 | 26 | 3- کاملا با جاوا همزیسته، هم میتونید در جاوا از کلاس ها و توابع کاتلین استفاده کنید و هم برعکس داخل کاتلین از جاوا. 27 | -------------------------------------------------------------------------------- /src/declaring-constants/README.md: -------------------------------------------------------------------------------- 1 |
2 | 3 | # constant ها 4 | 5 | مبحث بعدی که میخوام دربارش صحبت کنم Constant هاست. ما خیلی درمورد constant ها صحبت نکردیم تنها جایی که اشاره ای بهش شد زمانی بود که میخواستیم یک object بسازیم. خب حالا چجوری میتونیم Constant ها رو بسازیم، در واقع ما نحوه ساخت اون ها رو قبلا دیدیم 6 | 7 |
8 | 9 | ```kotlin 10 | object Copyright { 11 | val author = "Sina Darvishi" 12 | } 13 | ``` 14 | 15 |
16 | 17 | یک object ساختیم و یک خصیصه بهش دادیم. همین. در واقع فرقی با ساختن یک object که قبلا دیدیم نداره. ما درواقع از همین به عنوان constant استفاده میکنیم. 18 | 19 | و من میتونم توی هرجایی ازش استفاده کنم 20 | 21 |
22 | 23 | ```kotlin 24 | object Copyright { 25 | val author = "Sina Darvishi" 26 | } 27 | 28 | fun main(args: Array) { 29 | Copyright.author 30 | } 31 | ``` 32 | 33 | 34 |
35 | 36 | و درواقع من هر موقع پکیجش رو اضافه کنم میتونم از این استفاده کنم. 37 | 38 | همچنین ما میتونیم Constant ها رو به عنوان Top-Level معرفی کنیم 39 | 40 |
41 | 42 | ```kotlin 43 | val CopyrightAuthor = "Sina Darvishi" 44 | 45 | object Copyright { 46 | val author = "Sina Darvishi" 47 | } 48 | 49 | fun main(args: Array) { 50 | Copyright.author 51 | CopyrightAuthor 52 | } 53 | ``` 54 | 55 |
56 | 57 | خب درواقع این سوال پیش میاد که آیا من باید Constant ها رو توی جاهای رندوم قرارشون بدم و هر موقع خواستم صداشون بزنم؟ 58 | 59 | درواقع این به معماری برنامتون بستگی داره، به نظر من این خیلی بهتره که Constant ها رو توی یک Object دسته بندی کنین تا این که همه رو در هرجای برنامه استفاده کنیم. 60 | 61 | مثلا وقتی میخوایم تنظیمات یک Camera رو به صورت Constant نگه داری کنیم، یک object به عنوان CameraSettings درست کنیم و constant هارو توی اون نگه داریم. 62 | 63 |
64 | -------------------------------------------------------------------------------- /src/declaring-variables-in-kotlin/README.md: -------------------------------------------------------------------------------- 1 |
2 | 3 | # تعریف متغیر در کاتلین 4 | 5 | خب وارد بخش پایه ای کاتلین شدیم، اولین چیزی که میخوایم در موردش صحبت کنیم اینه که چگونه متغیر ایجاد کنیم. اول بیام یک فایل کاتلین به نام Variables توی پروژمون بسازیم. 6 | 7 | 8 | 9 | همینطور که میبینین به خاطر ساختر پکیجم اون بالا چه طور نوشته شده. بیاین `main` رو باز کنیم. 10 | 11 |
12 | 13 | ```kotlin 14 | fun main(args: Array) { 15 | 16 | } 17 | ``` 18 | 19 |
20 | 21 | همینطور که میبینید args در واقع نام متغیر و تایپ و اون هم از جنس Array هستش و این هم یک generic type هستش که بعدا در موردش صحبت میکنیم ولی مهمترین قسمتش سینتکس کد هستش، نام متغیر ، دونقطه و تایپ اون متغیر. 22 | حالا بیاین و یک متغیر داخل main بنویسیسم 23 | 24 |
25 | 26 | ```kotlin 27 | var streetNumber: Int 28 | ``` 29 | 30 |
31 | 32 | اگه دقت کنید IntelliJ میاد و streetNumber رو خاکستری میکنه و اینم تنها به این دلیله که ازش استفاده نشده و فعلا چیز مهمی نیست. میتونم بیام و یک متغیر دیگه بنویسم: 33 | 34 |
35 | 36 | ```kotlin 37 | var streetName : String = "High Street" 38 | ``` 39 | 40 |
41 | 42 | کاتلین در واقع اجازه میده که من متغیر رو همون اول که تعریف میکنم مقدار دهی بکنم، به عنوان مثال مقادار `High Street` رو به متغییر `streetName` دادم. یک چیز دیگه که لازمه بهش توجه کنید اینه که ما از کلیدواژه `var` استفاده کردیم، درواقع این کلیدواژه میگه که ایا این متغیر یک متغییر Immutable هست یا نه، به این معنی که میتونیم مقدار جدید بهش بدیم یا نه، درواقع یک کلید واژه دیگه هم هست به نام `val` که مثل `var` هست ولی با یک تفاوت، val یک متغییر رو Immutable میکنه و var یک متغییر رو mutable، به این معنی که میتونیم مقدار جدید به یک متغییر var بدیم ولی به val نه . 43 | مثلا مینویسیم 44 | 45 |
46 | 47 | ```kotlin 48 | val zip = "E11 P1" 49 | streetName = "Pudding Lane" 50 | zip = "SW1 ES2" 51 | ``` 52 | 53 |
54 | 55 | میبینیم که در خطی که داریم مقدار جدیدی به zip ارور داریم و اگه موس رو روی اون خط نگه داریم متوجه میشیم که IntelliJ میگه که نمیتونیم به متغیر val مقدار جدید بدیم. پس var به این معنی است که من دارم یک متغییر میسازم که اسیب پذیره یعنی میتونه مقدار جدید بگیره و زمانی که val مینویسیم به این معنیه که من دارم یک متغیر غیر آسیب پذیر تولید میکنم، یعنی نمیتونیم مقدار جدید بهشون بدیم. اگه حالا با Java اشنا باشین val انگار همون متغییریه که اولش final داشت. 56 | 57 | یک نکته دیگه هم بگم، ما در واقع نیازی نداریم که تایپ متغیر رو ذکر کنیم، یعنی میتونیم بنویسیم 58 | 59 |
60 | 61 | ```kotlin 62 | var streetName = "High Street" 63 | ``` 64 | 65 |
66 | 67 | و خود کامپایلر میفهمه که با streetName چه نوع تایپی رو بده و اونو بهش نسبت بده، البته این به این معنی نیستش که میتونیم وسط برنامه تایپش رو عوض کنیم. 68 | 69 |
70 | -------------------------------------------------------------------------------- /src/declaring-variables-in-kotlin/first-view-of-variables.PNG: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/KotlinFarsi/OpenSourceTutorials-Introduction/92e9b633b82753deae74fa498e634a58c863e1d0/src/declaring-variables-in-kotlin/first-view-of-variables.PNG -------------------------------------------------------------------------------- /src/deconstructing-values/README.md: -------------------------------------------------------------------------------- 1 |
2 | 3 | # deconstructing values 4 | 5 | ما دیدیم که زمانی که داریم به دوگانه ها یا سه گانه ها دسترسی پیدا میکنیم، هر دسترسی رو با استفاده از first و second و third انجام میدیم، خب البته مشکلی هم نیست ولی خب یکی از هدف های کاتلین این بود که دقیق تر کد بزنیم و این که بگیم اولی یا دومی یا سومی دقیق نیست یعنی اصلا اولی یا دومی چی هستند؟ و درواقع من باید برم به محل تعریف تابع تا متوجه بشم اولی چیه یا دومی یا سومی. 6 | 7 | به عنوان مثال کدی که نوشتیم رو نگاه کنین: 8 | 9 |
10 | 11 | ```kotlin 12 | fun capitalAndPopulation(country: String): Pair{ 13 | return Pair("Madrid",2000000) 14 | } 15 | 16 | fun main(args: Array) { 17 | val result = capitalAndPopulation("Spain") 18 | println(result.first) 19 | println(result.second) 20 | } 21 | ``` 22 | 23 |
24 | 25 | خب ما اینجا result رو داریم و در نتیجه میتونیم first و second رو بدست بیاریم، ولی first چه مقداری رو بهمون میداد ؟ یا second چی؟ خب برای این که بفهمیم میریم بالا و نگاه میکنیم میبینیم که String و Long رو داریم برمیگردونیم ولی بازم دیدگاهی نداریم که این دو نماینده چه متغییر هایی بودن. 26 | 27 | کاتلین برای حل این مشکل بهمون این امکان رو میده که متغییر هارو بشکنین، به عنوان مثال کد زیر رو نگاه کنین: 28 | 29 |
30 | 31 | ```kotlin 32 | fun capitalAndPopulation(country: String): Pair{ 33 | return Pair("Madrid",2000000) 34 | } 35 | 36 | fun main(args: Array) { 37 | val (capital,population) = capitalAndPopulation("Spain") 38 | 39 | println(capital) 40 | println(population) 41 | } 42 | ``` 43 | 44 |
45 | 46 | در واقع این به معنیه اینه که من میتون به جای این که جواب رو توی یک متغیر بریزم، جواب رو توی دومتغیر با نام دلخواه بریزم.البته این شکستن تنها برای چندگانه ها نیست. اگر به کد تعریف دوگانه ها یا سه گانه ها مراجعه کنید(در IntelliJ IDEA دکمه ctrl را نگه دارید و موس را برروی Pair ببرید و کلیک کنید) متوجه خواهید شد که درواقع دوگانه ها یا سه گانه ها کلاس های دیتای از پیش تعریف شده ای هستند که ما از انها استفاده میکنیم. پس همینطور که ما میتونیم برای دوگانه ها به عنوان مثال مقادیر خروجی رو بشکنیم، همین کار رو برای کلاس های دیتا هم میتونیم انجام بدیم. به عنوان مثال 47 | 48 |
49 | 50 | ```kotlin 51 | data class CustomerKotlin(var id: Int, var name: String, var email: String){ 52 | override fun toString(): String { 53 | return "{\"id\": \"$id\", \"name\": \"$name\"}" 54 | } 55 | } 56 | 57 | fun main(args: Array) { 58 | val (id,name,email) = CustomerKotlin(1,"Sina","Sinadarvi@gmail.com") 59 | println(id) 60 | println(name) 61 | println(email) 62 | } 63 | ``` 64 | -------------------------------------------------------------------------------- /src/enum-classes-in-kotlin/README.md: -------------------------------------------------------------------------------- 1 |
2 | 3 | # کلاس های enum در کاتلین 4 | 5 | رسیدم به بخش Enum که ساختشون راحت و استفاده ازشون راحت تر. به عنوان مثال کد زیر رو نگاه کنید. 6 | 7 |
8 | 9 | ```kotlin 10 | enum class Priority { 11 | MINOR, 12 | NORMAL, 13 | MAJOR, 14 | CRITICAL 15 | } 16 | 17 | fun main(args: Array) { 18 | val priority = Priority.NORMAL 19 | 20 | println(priority) 21 | } 22 | ``` 23 | 24 |
25 | 26 | خب حالا اگه من بیام و priority رو پرینت کنم چی میشه؟ ( با فشار دادن دکمه اجرا میتونین نتیجه رو ببینین) 27 | 28 | در اینجا کاتلین به صورت دیفالت میاد و مقدار اون enum رو به String تبدیل و چاپ میکنه. 29 | 30 | 31 | 32 | خب حالا فرض کنین میخوایم هر کدوم از enum هامون یک مقدار داشته باشن، یعنی یک خصیصه داشته باشیم به نام value و مثلا وقتی به NORMAL دسترسی پیدا کردیم، مقدار اونو بخونیم. 33 | 34 |
35 | 36 | ```kotlin 37 | enum class Priority(val value : Int ) { 38 | MINOR(-1), 39 | NORMAL(0), 40 | MAJOR(1), 41 | CRITICAL(10) 42 | } 43 | 44 | fun main(args: Array) { 45 | val priority = Priority.NORMAL 46 | 47 | println(priority.value) 48 | } 49 | ``` 50 | 51 |
52 | 53 | همچنین ما میتونیم از کامپایلر بخوایم که بهمون بگه این enum ای که ما میخوایم بهش دسترسی داشته باشیم چندمین enum توی کلاس خودشه. 54 | 55 |
56 | 57 | ```kotlin 58 | enum class Priority(val value : Int ) { 59 | MINOR(-1), 60 | NORMAL(0), 61 | MAJOR(1), 62 | CRITICAL(10) 63 | } 64 | 65 | fun main(args: Array) { 66 | val priority = Priority.NORMAL 67 | 68 | println(priority) 69 | println(priority.value) 70 | 71 | println(priority.ordinal) 72 | } 73 | ``` 74 | 75 |
76 | 77 | همچنین ما خصیصه name رو داریم 78 | 79 |
80 | 81 | ```kotlin 82 | enum class Priority(val value : Int ) { 83 | MINOR(-1), 84 | NORMAL(0), 85 | MAJOR(1), 86 | CRITICAL(10) 87 | } 88 | 89 | fun main(args: Array) { 90 | val priority = Priority.NORMAL 91 | 92 | println(Priority.CRITICAL.name) 93 | 94 | } 95 | ``` 96 | 97 |
98 | 99 | که اگه برنامه ران بشه، بهمون CRITICAL رو برمیگردونه. 100 | 101 | فرض کنین که میخوایم تموم enum های داخل کلاس رو لیست کنیم 102 | 103 |
104 | 105 | ```kotlin 106 | enum class Priority(val value : Int ) { 107 | MINOR(-1), 108 | NORMAL(0), 109 | MAJOR(1), 110 | CRITICAL(10) 111 | } 112 | 113 | fun main(args: Array) { 114 | 115 | for(priorityInList in Priority.values()) 116 | println(priorityInList) 117 | } 118 | ``` 119 | 120 |
121 | 122 | درواقع تابع values() میاد و یک لیست از تمومی مقدار های داخل کلاس Priority رو بهمون میده. 123 | 124 | 125 | 126 | اگه فرض کنیم بخوایم با استفاده از کلاس به مقدار یک enum دسترسی داشته باشیم از تابع valueOf() استفاده میکنیم 127 | 128 |
129 | 130 | ```kotlin 131 | enum class Priority(val value : Int ) { 132 | MINOR(-1), 133 | NORMAL(0), 134 | MAJOR(1), 135 | CRITICAL(10) 136 | } 137 | 138 | fun main(args: Array) { 139 | 140 | val p = Priority.valueOf("MAJOR") 141 | println(p) 142 | } 143 | ``` 144 | 145 |
146 | 147 | خب همونطور که دیدید وقتی یکی از enum هارو پرینت میکنیم در واقع نام اون enum رو برامون پرینت میکنه، همون کاری که با متغیر name انجام میدیم، ولی من میتونم بیام و تابع toString رو override کنم 148 | 149 |
150 | 151 | ```kotlin 152 | enum class Priority(val value : Int ) { 153 | MINOR(-1){ 154 | override fun toString(): String { 155 | return "Minor priority" 156 | } 157 | }, 158 | NORMAL(0), 159 | MAJOR(1), 160 | CRITICAL(10) 161 | } 162 | 163 | fun main(args: Array) { 164 | 165 | val priority = Priority. MINOR 166 | 167 | println(priority) 168 | } 169 | ``` 170 | 171 |
172 | 173 | خب، تا اینجا یاد گرفتیم چگونه از توابع و خصیصه های enum استفاده کنیم، حالا بیایم و یک تابع داخل enum بنویسیم 174 | 175 | ابتدا بیایم یک abstract داخل enum درست کنیم. 176 | 177 |
178 | 179 | ```kotlin 180 | enum class Priority(val value : Int ) { 181 | MINOR(-1){ 182 | override fun toString(): String { 183 | return "Minor priority" 184 | } 185 | }, 186 | NORMAL(0), 187 | MAJOR(1), 188 | CRITICAL(10) // بر روی این خط، هشداری دریافت خواهید کرد 189 | 190 | abstract fun text(): String 191 | } 192 | 193 | fun main(args: Array) { 194 | 195 | val priority = Priority. MINOR 196 | 197 | priority.text() 198 | } 199 | ``` 200 | 201 |
202 | 203 | خب اگه این کد رو بزنید متوجه میشید که کامپایلر بهتون ارور میده. یادتونه که گفتم یک جا هست که شما نیاز به نقطه ویرگول دارین ؟ اون اینجاست، بعد از اخرین enum یک نقطه ویرگول بذارین. 204 | 205 |
206 | 207 | ```kotlin 208 | enum class Priority(val value : Int ) { 209 | MINOR(-1){ 210 | override fun toString(): String { 211 | return "Minor priority" 212 | } 213 | }, 214 | NORMAL(0), 215 | MAJOR(1), 216 | CRITICAL(10); 217 | 218 | abstract fun text(): String 219 | } 220 | ``` 221 | 222 |
223 | 224 | درواقع وقتی شما حتی این نقطه ویرگول رو هم بذارید بازم کامپایلر بهتون ارور میده، البته نه این که ما کار اشتباهی کردیم، بلکه خب اینجا ما دوتا ارور داشتیم. توجه کنین که ما متد abstract رو درست کردیم، پس باید برای همه ی enum های داخل این کلاس این متد رو override کنیم. 225 | 226 |
227 | 228 | ```kotlin 229 | enum class Priority(val value : Int ) { 230 | MINOR(-1){ 231 | override fun text(): String { 232 | TODO("not implemented") //To change body of created functions use File | Settings | File Templates. 233 | } 234 | 235 | override fun toString(): String { 236 | return "Minor priority" 237 | } 238 | }, 239 | NORMAL(0) { 240 | override fun text(): String { 241 | TODO("not implemented") //To change body of created functions use File | Settings | File Templates. 242 | } 243 | }, 244 | MAJOR(1) { 245 | override fun text(): String { 246 | TODO("not implemented") //To change body of created functions use File | Settings | File Templates. 247 | } 248 | }, 249 | CRITICAL(10) { 250 | override fun text(): String { 251 | TODO("not implemented") //To change body of created functions use File | Settings | File Templates. 252 | } 253 | }; 254 | 255 | abstract fun text(): String 256 | } 257 | ``` 258 | 259 |
260 | 261 | خب حالا تنها کاری که باید بکنید اینه که برای هر enum بگید تابع مورد نظرتون میخواد چیکار انجام بده و تمام 262 | 263 |
264 | 265 | -------------------------------------------------------------------------------- /src/enum-classes-in-kotlin/result-1.PNG: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/KotlinFarsi/OpenSourceTutorials-Introduction/92e9b633b82753deae74fa498e634a58c863e1d0/src/enum-classes-in-kotlin/result-1.PNG -------------------------------------------------------------------------------- /src/enum-classes-in-kotlin/result-2.PNG: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/KotlinFarsi/OpenSourceTutorials-Introduction/92e9b633b82753deae74fa498e634a58c863e1d0/src/enum-classes-in-kotlin/result-2.PNG -------------------------------------------------------------------------------- /src/enum-classes-in-kotlin/result-3.PNG: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/KotlinFarsi/OpenSourceTutorials-Introduction/92e9b633b82753deae74fa498e634a58c863e1d0/src/enum-classes-in-kotlin/result-3.PNG -------------------------------------------------------------------------------- /src/extension-functions-from-java/README.md: -------------------------------------------------------------------------------- 1 |
2 | 3 | # توابع الحاقی کاتلین از جاوا 4 | 5 | اخرین موردی که میخوایم توی این بخش در موردش صحبت کنیم استفاده، صدازدن توابع الحاقی کاتلین از جاوا است. بیاین به فایل CustomerKotlin مراجعه کنیم و یک تابع الحاقی بهش اضافه کنیم 6 | 7 |
8 | 9 | ```kotlin 10 | fun CustomerKotlin.extention(){ 11 | 12 | } 13 | ``` 14 | 15 |
16 | 17 | و حالا اگه به فایل جاوامون مراجعه کنیم تنها به این روش میتونیم از این تابعمون استفاده کنیم: 18 | 19 |
20 | 21 | ```java 22 | CustomerKotlinKt.extention(customerKotlin); 23 | ``` 24 | 25 |
26 | 27 | درواقع ما اینجا از همون فایل استفاده میکنیم و چون میخوایم روی یک کلاس شی خاصمون این تابع رو اعمال کنیم، این شی رو به تابع پاس بدیم و در نهایت همون فرآیند که میخوایم روی اون شی به عمل میاد. 28 | 29 |
30 | -------------------------------------------------------------------------------- /src/extension-functions-in-kotlin-and-summary/README.md: -------------------------------------------------------------------------------- 1 |
2 | 3 | # عبارت های الحاقی در کاتلین و خلاصه بخش نهم 4 | 5 | کاتلین یک ویژگی خیلی مهم رو ساپورت میکنه به نام توابع الحاقی، که درواقع از C# الهام گرفته شده. ایده پشت این ویژگی اینه که من بتونم یک تابع رو به یک کلاس الحاق کنم بدون این که از اون کلاس ارث بری کنم 6 | 7 | کد زیر رو نگاه کنین: 8 | 9 |
10 | 11 | ```kotlin 12 | fun String.hello(){ 13 | println("It's me") 14 | } 15 | ``` 16 | 17 |
18 | 19 | در واقع اینجا یک الحاق به کلاس String انجام دادیم. یک تابع جدید به کلاس String اضافه کردیم که تنها یک رشته رو چاپ میکنه و برای استفاده ازش کافیه بنویسیم : 20 | 21 |
22 | 23 | ```kotlin 24 | fun String.hello(){ 25 | println("It's me") 26 | } 27 | 28 | fun main(args: Array) { 29 | "Sina".hello() 30 | } 31 | ``` 32 | 33 |
34 | 35 | 'و خب اگه اجراش کنین متوجه میشین که تابع الحاقیمون رو اجرا کرده. 36 | 37 | خب بیاین یک تابع مفیدتر بنویسیم: 38 | 39 |
40 | 41 | ```kotlin 42 | fun String.toTilteCase(): String { 43 | return this.split(" ").joinToString(" ") { it.capitalize() } 44 | } 45 | ``` 46 | 47 |
48 | 49 | نیاز نیست که حالا درمورد این زنجیره و توابع داخلش نگران باشین، چیزی که اینجا مهمه اینه که با استفاده از this مقدار خود String که این تابع به اون الحاق شده رو داخل تابع الحاقیمون استفاده کردیم. 50 | 51 |
52 | 53 | ```kotlin 54 | fun String.toTilteCase(): String { 55 | return this.split(" ").joinToString(" ") { it.capitalize() } 56 | } 57 | 58 | fun main(args: Array) { 59 | println("this is a sample string to title case".toTilteCase()) 60 | } 61 | ``` 62 | 63 | 64 | 65 |
66 | 67 | **خلاصه بخش 9:** 68 | 69 | 1- ما توی این قسمت نگاهی به توابع High-Order انداختیم و دیدیم که توابع High-Order حساب میشن که یا یک تابع رو به عنوان ورودی قبول کنن و یا این که تابع رو به عنوان خروجی پاس بدن 70 | 71 | 2- دیدم که کاتلین استفاده از Lambda را ممکن کرده 72 | 73 | 3- دیدم که کاتلین اجازه دسترسی به Closure های تغییر داده شده رو میده، به این معنی که اگر در داخل عبارت لاندامون از متغییری استفاده کردیم که تغییر میکنه، اون تغییر به داخل لاندامون هم سرایت میکنه. 74 | 75 | 4- و دیدیم که توابع الحاقی توابعی هستند که میتونیم اون هارو بدون ارث بری از کلاس به اون کلاس اضافه کنیم. که این کار رو درواقع برای کلاس های جاوا هم میتونیم انجام بدیم. 76 | 77 | 78 |
79 | -------------------------------------------------------------------------------- /src/extension-functions-in-kotlin-and-summary/result-1.PNG: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/KotlinFarsi/OpenSourceTutorials-Introduction/92e9b633b82753deae74fa498e634a58c863e1d0/src/extension-functions-in-kotlin-and-summary/result-1.PNG -------------------------------------------------------------------------------- /src/filtering-mapping-and-flatmapping-in-kotlin/README.md: -------------------------------------------------------------------------------- 1 |
2 | 3 | # مرور کوتاه بر روی filtering و mapping و flatmapping در کاتلین 4 | 5 | ما دیدم که چجوری میتونیم از کالکشن ها در کاتلین استفاده کنیم، حالا بیاین ببینیم چجوری میتونیم عمل های مختلف رو روشون انجام بدیم. 6 | 7 | خب اینجا من یک سری کد از قبل درست کردم: 8 | 9 |
10 | 11 | ```kotlin 12 | data class Album(val title: String, val year: Int, val chartUK: Int, val chartUS: Int, val tracks: List = listOf()) 13 | 14 | data class Track(val title: String, val durationInSeconds: Int) 15 | 16 | val albums = listOf( 17 | Album("The dark side of the moon", 1973,2,1, 18 | listOf(Track("Speak To me",90), 19 | Track("Breathe",163), 20 | Track("On the run",216), 21 | Track("Time",421), 22 | Track("The great gig in the sky",276), 23 | Track("Money",382), 24 | Track("Us and them",462), 25 | Track("Any color you like",205), 26 | Track("Brain Damage",228), 27 | Track("Eclipse",123) 28 | )), 29 | Album("The wall",1979,3,1), 30 | Album("Wish you were here",1975,1,1), 31 | Album("Animals",1977,2,3), 32 | Album("The piper at the gates of dawn",1967,6,131), 33 | Album("The final Cut",1983,1,6), 34 | Album("The middle",1971,3,70), 35 | Album("Atom heart mother",1970,1,55), 36 | Album("Ummagumma",1969,5,74), 37 | Album("More",1969,9,153)) 38 | ``` 39 | 40 |
41 | 42 | همینطور که میبینین در انتها یک سری آلبوم داریم که به همراه تاریخ و رتبه چارت آمریکا و انگلیس اومده. 43 | 44 | خب بیاید یکم با این کد بازی کنیم و در این بین هم من یک سری از توابعی که در دسترسه رو بهتون نشون میدم و البته که این ها همشون نیستن. 45 | 46 | به عنوان مثال بیاین فرض کنیم که میخوایم آلبوم هایی که در انگلیس رتبه اول بودن رو پیدا کنیم. 47 | 48 | من میدونم که یک سری آلبوم دارم و همینطور میدونم که هر آلبوم هم یک رتبه چارت انگلیس رو داخل خودش داره. 49 | 50 | خب یک راه غیر Functional برای حل این مسئله اینه که یک حلقه درست کنیم و بین آرایه بگردیم: 51 | 52 |
53 | 54 | ```kotlin 55 | fun main(args: Array) { 56 | 57 | for (album in albums) 58 | if (album.chartUK == 1) 59 | println("Found - ${album.title}") 60 | 61 | } 62 | ``` 63 | 64 |
65 | 66 | خب درواقع اینجا از یک for ساده استفاده کردیم. ولی بیاین یکم بهتر بنویسیم. خب ما این همه در مورد Functional Programming صحبت کردیم، بیایم یکم ازش استفاده کنیم. 67 | 68 |
69 | 70 | ```kotlin 71 | albums.forEach { if (it.chartUK == 1) println("Found - ${it.title}") } 72 | ``` 73 | 74 |
75 | 76 | اولین چیزی که میتونیم ازش استفاده کنیم، همینطور که میبینین، بهره بردن از forEach هه ، درواقع اینجا همون عمل بالا رو داریم انجام میدیم و در انتها هم مثل هر تابع لاندای دیگه از it برای پاس کاری استفاده کردیم. 77 | 78 | در واقع اگه کد forEach رو بررسی کنین متوجه میشین که تنها داره یک کالکشن رو دور میزنه و عمل رو انجام میده. 79 | 80 | بیاین این کد دیگه رو نگا کنیم: 81 | 82 |
83 | 84 | 85 | ```kotlin 86 | val albums1 = albums 87 | albums1.filter { it.chartUK == 1 } 88 | albums1.forEach { println("Found - ${it.title}") } 89 | ``` 90 | 91 |
92 | 93 | در واقع اینجا اومدیم و از تابع filter استفاده کردیم و کاری که این تابع انجام میده اینه که یک آرایه رو دریافت میکنه و متناسب با عملی که دایم و روی اون آرایه ها انجام داده نتیجه رو برمیگردونه. 94 | 95 | البته که من میتونم همین عبارت بالا رو زنجیرواری اینطوری بنویسم: 96 | 97 |
98 | 99 | ```kotlin 100 | albums.filter { it.chartUK == 1 }.forEach { println("Found - ${it.title}") } 101 | ``` 102 | 103 | بقیه این قسمت در حال اماده شدن میباشد 104 | -------------------------------------------------------------------------------- /src/function-with-default-and-named-parameters-in-kotlin/README.md: -------------------------------------------------------------------------------- 1 |
2 | 3 | # تابع با پارامترهای پیشفرض و نامیده شده 4 | 5 | حالا، یکی از ویژگی هایی که همراه کاتلین میاد اینه که توابعمون میتونن مقادیر پیشفرض داشته باشند. مثلا تابع sum رو نوشیتم که یادتون میاد.خب حالا فرض کنین من میخوام یک مقدار z هم در نظر بگیرم، که البته بعضی جاها نیاز به 2 پارامتر و بعضی جاها نیاز به 3 پارامتر داریم! یعنی بعضی جاها پارامتر سوممون به صورت دیفالت صفر باید درنظر گرفته بشه. 6 | 7 |
8 | 9 | ```kotlin 10 | fun sum(x:Int, y:Int, z:Int=0) = x+y+z 11 | 12 | fun main(args: Array) { 13 | sum(1,2,3) 14 | sum(1,2) 15 | } 16 | ``` 17 | 18 |
19 | 20 | نگاه کنین، کامپایلر میاد نگاه میکنه،اگه پارامتر سوم فراهم شده بود که همون مقدار رو استفاده میکنه، اگه پارامتر سوم فراهم نشده بود از مقدار دیفالت استفاده میکنه! و این خوبه، چراکه بهمون این قابلیت رو میده که یک تابع با چندین پارامتر دیفالت داشته باشیم و از تکرار بی مورد(overload) توابع جلوگیری کنیم. مثلا توی جاوا اگر میخواستیم یک تابع داشته باشیم که در بعضی مواقع دو ورودی میگرفت و در بعضی مواقع 3 ورودی، این کار امکان پذیر نبود و برای عملی شدن آن باید 2 تابع مینوشتیمف یکی با 2 ورودی و یکی با 3 ورودی که خب این مشکل در کاتلین رفع شده است. 21 | 22 | خب بیاین یک تابع دیگه رو مثال بزنیم،مثلا 23 | 24 |
25 | 26 | ```kotlin 27 | fun printDetails(name: String,email: String="",phone: String){ 28 | println("name : $name - email : $email - phone : $phone") 29 | } 30 | ``` 31 | 32 |
33 | 34 | اومدم یک تابع درست کردم که مقدار اول و سوم رو درخواست میکنه ولی اگه مقدار دوم وارد نشد به صورت دیفالت یک مقدار جایگزینش میشه. حالا کد main رو هم مینویسم 35 | 36 |
37 | 38 | ```kotlin 39 | printDetails("Sina Darvishi","555 87 345") 40 | ``` 41 | 42 |
43 | 44 | برای مقدار name نام خودم رو دادم و برای مقدار شماره هم شماره خودم رو وارد کردم. ولی وقتی اجراش کنیم متوجه میشیم که ارور میده، دلیلش هم اینه که مقدار شماره تلفن رو که من به عنوان دومین ورودی وارد کردم رو به عنوان email میگیره! در واقع میمونه که شما دارین پارامتر phone رو پاس میدین یا پارامتر email . برای رفع این مشکل هم راه حل خیلی ساده ای داریم، کاتلین این قابلیت رو توی کد نویسی به توسعه دهنده میده که وقتی میخواین به یک تابع مقدار بدین، دقیق مشخص کنین که به کدوم پارامتر میخواین مقدار بدین، پس کد درست بالا میشه: 45 | 46 |
47 | 48 | ```kotlin 49 | printDetails("Sina Darvishi",phone = "555 87 345") 50 | ``` 51 | 52 |
53 | 54 | در ضمن این خاصیت این قابلیت رو به ما میده که ما خارج از ترتیبی که تابع رو تعریف و پارامتر های اونو درخواست کردیم به تابع ورودی بدیم. 55 | در ضمن این قابلیت در واقع اونجایی خوبه که ما تعداد زیادی پارامتر ورودی میخوایم و در واقع گیج میشیم که کدوم ورودی برای کدوم پارامتره و ما با نام دهی به مقادیری که میخوایم به تابع پاس بدیم از این گیج شدن جلوگیری میکنیم. 56 | 57 | 58 | -------------------------------------------------------------------------------- /src/function-with-unlimited-parameters-in-kotlin-and-summary/README.md: -------------------------------------------------------------------------------- 1 |
2 | 3 | # تابع با پرامترهای نامحدود و خلاصه بخش چهارم 4 | 5 | اخرین بخشی که میخوایم در قسمت توابع به اون نگاه کنیم، پاس دادن تعداد نامشخص پارامتر های ورودی به تابعه. به عنوان مثال من میخوام تابعی رو تعریف کنم که قبل از این که از اون استفاده کنم، تعداد نامحدودی پارامتر ورودی قبول کنه. 6 | 7 |
8 | 9 | ```kotlin 10 | fun printStrings(vararg strings:String){ 11 | for(string in strings){ 12 | println(string) 13 | } 14 | } 15 | ``` 16 | 17 |
18 | 19 | تابع بالا رو نگاه کنین، با استفاده از کلید واژه vararg این مفهوم رو به کامپایلر میدم که من میخوام تابعی رو استفاده کنم که تعداد ورودی هاش مشخص نیست ولی همه انها از جنس رشته هستند. 20 | 21 | حالا من میتونم از این تابع استفاده کنم 22 | 23 |
24 | 25 | ```kotlin 26 | printStrings("1") 27 | printStrings("1","2") 28 | printStrings("1","2","3") 29 | ``` 30 | 31 |
32 | 33 | و هر چه قدر که ورودی دلم بخواد به تابع پاس بدم. 34 | 35 | فقط یک نکته اینجا هست، اگر من بخوام این vararg رو به یک تابع دیگه پاس بدم چه طور باید عمل کنم 36 | 37 |
38 | 39 | ```kotlin 40 | fun printStrings(vararg strings:String){ 41 | realyPrintStirngs(*strings) 42 | } 43 | 44 | fun realyPrintStirngs(vararg strings: String) { 45 | for (string in strings) { 46 | println(string) 47 | } 48 | } 49 | ``` 50 | 51 |
52 | 53 | واقعیتش راه حل خیلی ساده است، باید یک تابع دیگه بسازیم که vararg بگیره ولی خود پارامتر vararg رو مستقیم به تابع پاس ندیم.مثلا در اینجا string رو مستقیم پاس ندیم بلکه با استفاده از "*" قبل نام پارامتر اونو پاس بدیم! 54 | 55 | **خلاصه بخش 4** 56 | 57 | 1- توابع با استفاده از کلیدواژه fun ساخته میشوند 58 | 59 | 2- به صورت پیشفرص یک تابع تایپ Unit رو به عنوان پارامتر بازگشتی برمیگردونه 60 | 61 | 3- توی توابع به ما اجازه داده شده تا از 62 | 63 | - پرامتر های پیشفرص داشته باشیم 64 | 65 | - از پارامتر های نام دهی شده استفاده کنیم 66 | 67 | - و بی شمار ورودی برای یک تابعمون درنظر بگیریم 68 | 69 | 70 | 71 | -------------------------------------------------------------------------------- /src/functions-in-kotlin/README.md: -------------------------------------------------------------------------------- 1 |
2 | 3 | # توابع در کاتلین 4 | 5 | کاتلین یک زبان شی گرا توصیف شده است ولی درواقع یک زبان تابع محور یا به اصطلاح Functional نیز هست به این صورت که ما با توابع به مانند کلاس ها رفتار میکنیم.البته خیلی بحث در مورد functional بودن یا نبودن زبان کاتلین هست ولی از نظر خیلیا همین که توابع رو بتونیم پاس کاری کنیم و به صورت اشیا با انها برخورد کنیم این زبون رو functional میکنه.و حالا میایم و یکم در مورد توابع صحبت میکنیم، چگونه ساخته میشن، چگونه استفاده میشن و غیره و غیره . 6 | 7 | من یک فایل به نام Functions توی پکیج functions ساختم.میخوایم توابع مختلف رو بررسی کنیم و ببینیم چجوری ساخته میشن. اساسا به خاطر این که ما Top-Level-Functions هارو توی کاتلین داریم نیازی به این قضیه نیست که شما برای ساختن یک تابع نیاز به یک کلاس داشته باشین که درواقع اون تابعمون رو نگه داره و در واقع ما میتونیم توابع رو داخل فایل بنویسیم دقیقا مثل تابع Main که قبلا درست میکردیم. 8 | 9 | خب حالا بیاین و کد زیر و نگاه کنین 10 | 11 |
12 | 13 | ```kotlin 14 | fun hello(){ 15 | println("Hello") 16 | } 17 | 18 | fun main(args: Array) { 19 | hello() 20 | } 21 | ``` 22 | 23 |
24 | 25 | یه تابع ساختم به اسم hello و تنها کاری میکنه این یک Hello پرینت میکنه. تابع main رو هم ساختیم و تابع hello رو توش صدا کردیم. 26 | 27 | توجه کردین که تابع hello هیچ ورودی رو نگرفت و تنها کلید واژه fun رو داشتیم که مشخص میکنه تابع میخوایم بسازیم و همچنین هیچگونه تایپی که بخوایم برگردونیمش هم مشخص نکردیم. و وقتی میخواستیم صداش کنیم تنها کاری که کردیم این بود که نام hello به علاوه پرانتز هاش صدا زدیم.همین. همینطور که گفتم این تابع return نداره، درواقع توی زبون های برنامه نویسی دیگه این یک تابع void است یا اگه بخوایم کاتلینی صحبت کنیم این تابع درواقع داره Unit رو برمیگردونه، پس اگه بخوایم میتونیم همین تابع رو به این صورت بنویسیم 28 | 29 |
30 | 31 | ```kotlin 32 | fun hello(): Unit{ 33 | println("Hello") 34 | } 35 | ``` 36 | 37 |
38 | 39 | درواقع تنها کاری که کردیم اینه که return type رو مشخص کردیم. 40 | 41 | Unit تقریبا میشه گفت همون void خودمونه ولی خب اگر به سمت تعریف Unit هدایت بشین متوجه میشین که این درواقع یک object هست که میتونیم با اشیا دیگه مقایسه کردش و درواقع من میتونم بگم "اگه این تابع داره Unit برمیگردونه یک کاری رو انجام بده" و خب این یک ویژگی خوب میتونه باشه که بعدا بدردمون بخوره. 42 | 43 | اینجا میخوام یک نکته یکم سطح بالاتر بگم. در کاتلین ما میتونیم مقدار خروجی رو یک تایپ دیگه معرفی کنیم به نام Nothing . درواقع اگه دوباره به تعریف Nothing رجوع کنین متوجه میشین که صرفا یک کلاس خالیه.خب این جایی به دردمون میخوره که مثلا میخوایم بگین این تابع هیچ مقداری برنمیگردونه ولی میاد و یک Exception رو پرت میکنه. مثلا تابع زیر رو نگاه کنین 44 | 45 |
46 | 47 | ```kotlin 48 | fun throwingException(): Nothing{ 49 | throw Exception("This function throws an exception") 50 | } 51 | ``` 52 | 53 |
54 | 55 | اینجا ما یک تابع نوشتیم که هیچ مقداری رو برنمیگردونه (Nothing) و در واقع داره یک Exception رو برمیگردونه. 56 | 57 | خب پس اینجا متوجه شدین که اگر حتی return type رو ننویسین در واقع داریم Unit برمیگردونیم ولی اگه بخوایم تابعی بنویسیم که هیچی برنگردونه باید از Nothing استفاده کنیم. 58 | 59 | خب حالا اگه من بخوام یک تابع برگردونم که یک مقداری رو برمیگردونه، مثلا کد زیر رو نگاه کنین 60 | 61 |
62 | 63 | ```kotlin 64 | fun returnAFour(): Int{ 65 | return 4 66 | } 67 | 68 | fun main(args: Array) { 69 | val value = returnAFour() 70 | } 71 | ``` 72 | 73 |
74 | 75 | اومدیم یک تابع ساختیم که تایپ بازگشتیش Intه ، و داره مقدار 4 رو برمیگردونه و بعدشم اومدیم توی تابع main یک متغیر ساختیم که مقدار رو به اون پاس بده. 76 | 77 | حالا میخوایم به تابع یک مقدار پاس بدیم 78 | 79 |
80 | 81 | ```kotlin 82 | fun takingString(name: String){ 83 | println(name) 84 | } 85 | 86 | fun main(args: Array) { 87 | takingString("Some Value") 88 | } 89 | ``` 90 | 91 |
92 | 93 | حالا اگه فرض کنیم تابعی داشته باشیم که مقادیری رو از ورودی بگیره و به خروجی پاس بده 94 | 95 |
96 | 97 | ```kotlin 98 | fun sum(x:Int, y:Int):Int{ 99 | return x+y 100 | } 101 | 102 | fun main(args: Array) { 103 | sum(2,3) 104 | } 105 | ``` 106 | 107 |
108 | 109 | البته میتونیم توابع ساده بالا رو به صورت دیگه هم نوشت، مثلا تابع sum رو به این صورت بنویسیم 110 | 111 |
112 | 113 | ```kotlin 114 | fun sum(x:Int, y:Int) = x+y 115 | ``` 116 | 117 |
118 | 119 | توجه کنین که تابع بالا دقیقا عملکردی به مانند قبل خودش داره، و هیچ گونه تایپ بازگشتی مشخص نشده، کامپایلر اینجا با توجه به این که مقادیر ورودی x و y هستند تایپ مقدار خروجی رو خودش لحاظ میکنه و کارمون رو راحت تر میکنه. 120 | 121 | 122 | 123 | -------------------------------------------------------------------------------- /src/higher-order-functions-in-kotlin/README.md: -------------------------------------------------------------------------------- 1 |
2 | 3 | # توابع Higher-Order 4 | 5 | زمانی که در مورد توابع در کاتلین صحبت شد به این اشاره کردم که باید بتونیم با توابع به صورت کلاس های شهروند مرتبه اول برخورد کنیم و یکی از ویژگی های مهمی که یک زبون رو Functional میکنه اینه که توابعش بتونن به صورت Higher-Order ظاهر شن و اگر با مفهوم Higher-Order اشنا نیستین به این معنیه که توابع بتونن توابع دیگر رو به صورت پارامتر ورودی قبول کنن یا این که یک تابع بتونه توابع دیگر رو برگردونه. کاتلین این رو و البته چیز های دیگه ای مثل عبارت های Lambda و یا توابع بی نام و غیره و غیره رو هم ساپورت میکنه و الان میخوایم ببنیم چجوری میتونیم از تموم ویژگی های یک زبان Functional استفاده کنیم. 6 | 7 | بیاین چند خط کد بنویسیم: 8 | 9 |
10 | 11 | ```kotlin 12 | fun operation(x: Int, y: Int,op: (Int,Int)->Int): Int { 13 | return op(x,y) 14 | } 15 | ``` 16 | 17 |
18 | 19 | یک تابع نوشتیم به نام operation که دو متغیر x و y و همچنین یک تابع دیگر رو به عنوان ورودی دریافت میکنه که البته این تابع ورودی، دو متغیر از جنس Int دریافت میکنه و یک مقدار Int برمیگردونه و در انتها هم ما مقدار x و y رو به تابع op دادیم و مقدارش رو برمیگردونیم.به همین سادگی در کاتلین یک تابع High-Order نوشتیم. 20 | 21 | خب ما چطور میتونیم از این استفاده کنیم؟ مسلما باید یک تابع بنوسیم که با الگو (Int,Int) -> Int جور دربیاد، به عنوان مثال تابع زیر رو درنظر بگیرین 22 | 23 |
24 | 25 | ```kotlin 26 | fun sum(x: Int, y: Int) = x + y 27 | ``` 28 | 29 |
30 | 31 | توی کاتلین برای صدا زدن به وسیله نام اون تابع باید از "::" استفاده کنیم 32 | 33 |
34 | 35 | 36 | ```kotlin 37 | fun operation(x: Int, y: Int,op: (Int,Int)->Int): Int { 38 | return op(x,y) 39 | } 40 | 41 | fun sum(x: Int, y: Int) = x + y 42 | 43 | fun main(args: Array) { 44 | println(operation(2,3,::sum)) 45 | } 46 | ``` 47 | 48 |
49 | 50 | شما توی کاتلین هرجور که دوست دارین میتونین توابع High-Order بنویسین: 51 | 52 |
53 | 54 | ```kotlin 55 | fun operation(x:Int, op: (Int)-> Unit){ 56 | 57 | } 58 | 59 | fun route(path: String,vararg actions: (String,String)-> String){ 60 | 61 | } 62 | ``` 63 | 64 |
65 | 66 | و هیچ گونه محدودیتی در استفاده از توابع High-Order نداریم. 67 | 68 |
69 | 70 | 71 | -------------------------------------------------------------------------------- /src/higher-order-functions-in-kotlin/result-1.PNG: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/KotlinFarsi/OpenSourceTutorials-Introduction/92e9b633b82753deae74fa498e634a58c863e1d0/src/higher-order-functions-in-kotlin/result-1.PNG -------------------------------------------------------------------------------- /src/inheritance-in-kotlin/README.md: -------------------------------------------------------------------------------- 1 |
2 | 3 | # ارث بری در کاتلین 4 | 5 | کاتلین ارث بری رو مثل بقیه زبون های شی گرا ساپورت میکنه و توی کاتلین، کلاس پایه ای همه ی کلاس ها Any هستش. یعنی درواقع اگه یک کلاس باز کنم به این فرم 6 | 7 |
8 | 9 | ```kotlin 10 | class Customer 11 | ``` 12 | 13 |
14 | 15 | در واقع هیچ فرقی نداره با این که کلاسی باز کنم به این فرم 16 | 17 |
18 | 19 | ```kotlin 20 | class Customer: Any() 21 | ``` 22 | 23 |
24 | 25 | خب حالا بیاین یه کلاس پدر برای Customer بسازیم. 26 | 27 |
28 | 29 | ```kotlin 30 | class Person 31 | 32 | class Customer: Person() 33 | ``` 34 | 35 |
36 | 37 | فقط یادتون باشه وقتی کلاس رو inherit میکنین کانستراکتورش رو هم مشخص کنین. 38 | 39 | اگه کد بالا رو بزنین متوجه میشین که ارور توی برنامتون هست.مشکل اینجاست که توی کاتلین همه ی تایپ ها final هستند بنابراین نمیشه ازشون ارث بری بشه.یه جورایی میشه گفت برعکس جاوا که همیشه میتونیم ارثبری کنیم مگر این که final باشه، توی کاتلین هم میشه گفت همیشه میتونیم از یک کلاس ارث بری کنیم اگر اون کلاس open باشه. 40 | 41 |
42 | 43 | ```kotlin 44 | open class Person 45 | 46 | class Customer: Person() 47 | ``` 48 | 49 |
50 | 51 | برای توابع هم اگه میخوایم ازشون ارث بری بشه باید open قبلشون بیاد 52 | 53 |
54 | 55 | ```kotlin 56 | open class Person{ 57 | open fun validate(){ 58 | 59 | } 60 | } 61 | 62 | class Customer: Person(){ 63 | override fun validate() { 64 | super.validate() 65 | } 66 | } 67 | ``` 68 | 69 |
70 | 71 | خب حالا اگه به همراه main بخوایم تابع validate رو صدا کنیم داریم 72 | 73 |
74 | 75 | ```kotlin 76 | open class Person{ 77 | open fun validate(){ 78 | 79 | } 80 | } 81 | 82 | class Customer: Person(){ 83 | override fun validate() { 84 | super.validate() 85 | } 86 | } 87 | 88 | fun main(args: Array) { 89 | val customer = Customer() 90 | 91 | customer.validate() 92 | } 93 | ``` 94 | 95 |
96 | 97 | خب حالا فرض کنین توی Customer هستیم و میخوایم کانستراکتور پدرش رو صدا بزنیم، یادتونه گفتیم یه کانستراکتور دوم داریم؟ اینجا تقریبا میخوایم از همون استفاده کنیم، با این تفاوت که به جای this باید از super استفاده کنیم 98 | 99 |
100 | 101 | ```kotlin 102 | open class Person{ 103 | open fun validate(){ 104 | 105 | } 106 | } 107 | 108 | class Customer: Person{ 109 | override fun validate() { 110 | super.validate() 111 | } 112 | 113 | constructor():super(){ 114 | 115 | } 116 | } 117 | ``` 118 | 119 |
120 | 121 | فقط اینجا توجه کنین که علاوه بر این که به جای this از super استفاده کردیم پس باید کانستراکتور Person رو زمان ارث بری حذف کنیم، یعنی مثلا اینجا اومدیم و پرانتز های جلوی Person رو برداشتیم. 122 | 123 |
124 | 125 | 126 | 127 | 128 | 129 | 130 | 131 | -------------------------------------------------------------------------------- /src/installing-the-tooling/README.md: -------------------------------------------------------------------------------- 1 |
2 | 3 | # نصب کردن ابرازآلات 4 | 5 | خب بیشتر این دوره کدنوشتنه و اگه شما بتونین هم پای من بیاین و کد بزنین خیلی بهتر میشه. 6 | 7 | برای این که شروع کنیم شما به یک سری نرم افزار و ابزار ها نیاز دارین. خب مسلما به JDK نیاز خواهید بود که ما به نام Java Development Kit میشناسیمش و شما میتونین از نسخه 6 یا 7 یا 8 استفاده کنید. شما همچنین به کامپایلر Kotlin نیاز خواهید داشت و همچنین یک Editor و یا یک IDE . 8 | 9 | من قراره از IntelliJ IDEA استفاده کنم ولی شما میتونین از هر IDE که دلتون میخواد و کاتلین رو ساپورت کنه استفاده کنین. 10 | -------------------------------------------------------------------------------- /src/interfaces-in-kotlin/README.md: -------------------------------------------------------------------------------- 1 |
2 | 3 | # کلاس های interface در کاتلین 4 | 5 | به مانند کلاس های abstract ما مفهومی به نام interface داریم که مسلما کاتلین پشتیبانیش میکنه. 6 | 7 | اول شروع کنیم و یک کلاس interface به نام CustomerRepository بسازیم 8 | 9 |
10 | 11 | ```kotlin 12 | class Customer 13 | 14 | interface CustomerRepository { 15 | fun getById(id: Int) : Customer 16 | } 17 | 18 | class SQLCustomerRepository: CustomerRepository{ 19 | override fun getById(id: Int): Customer { 20 | TODO("not implemented") 21 | } 22 | } 23 | ``` 24 | 25 |
26 | 27 | همونطور که میبینین یک کلاس SQLCustomerRepository ساختیم که میاد از این interface استفاده میکنه و چون از یک interface استفاده میکنه باید توابع های اونو رو هم implement کنیم که همون getById اه. 28 | 29 | حالا بیاین برگردیم به CustomerRepository و یک چند خط کد اضافه کنیم بهش 30 | 31 |
32 | 33 | ```kotlin 34 | class Customer 35 | 36 | interface CustomerRepository { 37 | fun store(obj:Customer){ 38 | //implement code to store 39 | } 40 | fun getById(id: Int) : Customer 41 | } 42 | 43 | class SQLCustomerRepository:CustomerRepository{ 44 | override fun getById(id: Int): Customer { 45 | TODO("not implemented") 46 | } 47 | } 48 | ``` 49 | 50 |
51 | 52 | که درواقع اینجا اصلا مهم نیست که چه کدی توی بدنه store زده شده، مهم اینه که این تابع بدنه داره، اونم توی interface! و این با مفهوم interface توی زبان های برنامه نویسی دیگه متفاوته. به عنوان مثال توی #C یک اینترفیس نباید هیچگونه بدنه داشته باشه، اگه بخواین همچین کاری بکنین شما باید از کلاسی استفاده کنین به نام abstract که قبلا دربارش صحبت کردیم. در واقع در جاوا 8 کلیدواژه default برای توابع interface معرفی شد که کارش این بود که به مانند کلاس های abstract این قابلیت رو به interface بدیم که تابعی با بدنه داشته باشیم. به عنوان مثال کد زیر رو نگاه کنید: 53 | 54 |
55 | 56 | ```java 57 | public interface FourLegs { 58 | int legs = 4; 59 | 60 | default void walking(){ 61 | System.out.println("walking with 4 legs"); 62 | } 63 | 64 | void havingFourLegs(); 65 | } 66 | 67 | ``` 68 | 69 |
70 | 71 | همینطور که میبینید تابع walking رو داریم که در داخل interface با کلیدواژه ای به نام default پیاده سازی شده و این امکان رو به کلاسی که ازش implement میشه داده ک ه از این تابع استفاده کنه. توی کاتلین هم interface ها میتونن پیاده سازی دلخواه خودشونو داشته باشن ولی این برامون سوال ایجاد میکنه که دقیقا interface چه تفاوتی با abstract داره ؟ 72 | 73 | من نمیتونم کلاسی داشته باشم که از دوتا کلاس ارث بری کنه در حالی که میتونم کلاسی داشته باشم که از کلاسی ارث بری کنه که اون کلاس از چند interface استفاده میکنه. (به قولی ما نمیتونیم توی interface یک وضعیت رو حفظ کنیم) 74 | 75 | همینطور که گفتم interface ها میتونن خصیصه داشته باشند، که این خصیصه ها abstract باشند. 76 | 77 | به عنوان مثال اگه فرض کنین من بیام و یک متغیر به فرم زیر تعریف کنم و بهش مقدار بدم 78 | 79 | 80 |
81 | 82 | ```kotlin 83 | class Customer 84 | 85 | interface CustomerRepository { 86 | val isEmpty: Boolean = true 87 | 88 | fun store(obj:Customer){ 89 | //implement code to store 90 | } 91 | fun getById(id: Int) : Customer 92 | } 93 | ``` 94 | 95 |
96 | 97 | با اروری مواجه میشم که میگه نمیشه به خصیصه های interface مقداردهی کرد. البته میتونیم از getter و setter استفاده کنیم! 98 | 99 |
100 | 101 | ```kotlin 102 | class Customer 103 | 104 | interface CustomerRepository { 105 | val isEmpty: Boolean 106 | get() = true 107 | 108 | fun store(obj:Customer){ 109 | //implement code to store 110 | } 111 | fun getById(id: Int) : Customer 112 | } 113 | ``` 114 | 115 |
116 | 117 | توی اینترفیس ها یادگرفتیم که میتونیم توابع رو override کنیم، درواقع خصیصه هارو هم میتونیم override کنیم 118 | 119 |
120 | 121 | ```kotlin 122 | class Customer 123 | 124 | interface CustomerRepository { 125 | val isEmpty: Boolean 126 | get() = true 127 | fun store(obj:Customer){ 128 | //implement code to store 129 | } 130 | fun getById(id: Int) : Customer 131 | } 132 | 133 | class SQLCustomerRepository:CustomerRepository{ 134 | override fun getById(id: Int): Customer { 135 | TODO("not implemented") 136 | } 137 | 138 | override val isEmpty: Boolean 139 | get() = false 140 | } 141 | ``` 142 | 143 |
144 | 145 | خب ما خصیصه هایی داخل interface داشتیم و تونستیم اونارو override کنیم، درمورد عضوهای توابع interface که implement کردیمشون چی؟ ایا میشه اونا رو هم override کرد؟ درواقع اره،میتونیم. 146 | 147 |
148 | 149 | ```kotlin 150 | class Customer 151 | 152 | interface CustomerRepository { 153 | val isEmpty: Boolean 154 | get() = true 155 | fun store(obj:Customer){ 156 | //implement code to store 157 | } 158 | fun getById(id: Int) : Customer 159 | } 160 | 161 | class SQLCustomerRepository:CustomerRepository{ 162 | override fun getById(id: Int): Customer { 163 | return Customer() 164 | } 165 | 166 | override fun store(obj: Customer) { 167 | //my own implementation 168 | } 169 | 170 | override val isEmpty: Boolean 171 | get() = false 172 | } 173 | ``` 174 | 175 |
176 | 177 | اینجا همینطور که میبینین با این که store قبلا پیاده سازی شده بود ولی میتونیم اونو override کنیم و پیاده سازی خودمون رو انجام بدیم. 178 | 179 | خب از این موضوع بگذریم، بیاین کد زیر رو نگاه کنین: 180 | 181 |
182 | 183 | ```kotlin 184 | interface Interface1 { 185 | fun funA(){ 186 | println("fun A from Interface 1") 187 | } 188 | } 189 | 190 | interface Interface2 { 191 | fun funA(){ 192 | println("fun A from Interface 2") 193 | } 194 | } 195 | 196 | class Class1And2 : Interface1,Interface2{ 197 | override fun funA() { 198 | println("Our Own") 199 | } 200 | } 201 | 202 | fun main(args: Array) { 203 | val c = Class1And2() 204 | c.funA() 205 | } 206 | ``` 207 | 208 |
209 | 210 | دو اینترفیس داریم که دو 2 تابع هم نام رو داخل خودشون implement کردن و یک کلاس داریم که هردو اینترفیس رو implement میکنه و دوباره همون تابع با همون اسم رو override میکنه. حالا اگه داخل main اون تابع رو صدا بزنیم نتیجه چی میشه ؟ 211 | 212 | 213 | 214 | خب مسلما چون داخل کلاس Class1And2 دوباره متد funA رو پیاده سازی کردیم، همین یکی اجرا خواهد شد. اگه یادتون باشه ما میتونستیم از کلیدواژه super استفاده کنیم، ولی خب حالا اگه بیایم و اینجوری بنویسیم 215 | 216 | 217 |
218 | 219 | ```kotlin 220 | interface Interface1 { 221 | fun funA(){ 222 | println("fun A from Interface 1") 223 | } 224 | } 225 | 226 | interface Interface2 { 227 | fun funA(){ 228 | println("fun A from Interface 2") 229 | } 230 | } 231 | 232 | class Class1And2 : Interface1,Interface2{ 233 | override fun funA() { 234 | super.funA() 235 | } 236 | } 237 | 238 | fun main(args: Array) { 239 | val c = Class1And2() 240 | c.funA() 241 | } 242 | ``` 243 | 244 |
245 | 246 | کامپایلر میمونه و ارور میده! چراکه نمیدونه منظور کدوم funA هه،آیا میخوای از متد Interface1 استفاده کنی یا از Interface2 ؟ اگر مثلا یکی شون پیاده سازی نشده بود خب مشکلی نبود و کامپایلر میفهمید منظور کدومه ولی حالا که هردو پیاده سازی شدن چی؟ 247 | 248 | خب این مشکل با استفاده از “<>” قابل حله.مثلا فرض کنین من میخوام Interface2 رو تغییر بدم.کافیه کدم رو اینجوری بنویسم 249 | 250 |
251 | 252 | ```kotlin 253 | interface Interface1 { 254 | fun funA(){ 255 | println("fun A from Interface 1") 256 | } 257 | } 258 | 259 | interface Interface2 { 260 | fun funA(){ 261 | println("fun A from Interface 2") 262 | } 263 | } 264 | 265 | class Class1And2 : Interface1,Interface2{ 266 | override fun funA() { 267 | super.funA() 268 | } 269 | } 270 | 271 | 272 | fun main(args: Array) { 273 | val c = Class1And2() 274 | c.funA() 275 | } 276 | ``` 277 | 278 |
279 | 280 | و خب اینجوری نشون میدم که میخوام کدوم یکی رو تغییر بدم. 281 | 282 |
283 | -------------------------------------------------------------------------------- /src/interfaces-in-kotlin/result-1.PNG: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/KotlinFarsi/OpenSourceTutorials-Introduction/92e9b633b82753deae74fa498e634a58c863e1d0/src/interfaces-in-kotlin/result-1.PNG -------------------------------------------------------------------------------- /src/interop-with-java-7-and-8-and-summary/README.md: -------------------------------------------------------------------------------- 1 |
2 | 3 | # همکاری با جاوا 7 و 8 و خلاصه بخش دهم 4 | 5 | ما گفتیم که کاتلین قابلیت همکاری با Java 6.0 رو هم داره به این معنی که هرچی که روی جاوا 6 اجرا میشه ( به عنوان مثال اندروید) میتونه روی کاتلین هم اجرا بشه پس نیازه که Java 6.0 رو هم هدفمون قرار بدیم. به عنوان مثال توابع Lambda در جاوا 6 کلاس های بی نام هستن. 6 | 7 | 8 | **خلاصه بخش 10:** 9 | 10 | 1- متوجه شدیم که هم از کاتلین میتونیم به فایل جاوا دسترسی داشته باشیم و هم از جاوا به کاتلین 11 | 12 | 2- این که یک مقدار null باشه یا نه به توسعه دهنده بستگی داره و همچنین قابلیت استفاده از Annotation ها رو هم داریم 13 | 14 | 3- میتونیم از API های 8 و 7 استفاده کنیم 15 | 16 | -------------------------------------------------------------------------------- /src/interoperability-with-java/README.md: -------------------------------------------------------------------------------- 1 |
2 | 3 | # همکاری با جاوا 4 | 5 | در ابتدای این دوره دیدیم که در بعضی مواقع از کلاس های جاوا استفاده کردیم ولی توی این قسمت میخوایم بیشتر روی قابلیت همکاری کاتلین صحبت کنیم و همینطور که چندبار در طول این دوره اشاره کردم، کاتلین به راحتی میتونه با کلاس ها و توابع جاوا همکاری و ارتباط برقرار کنه به این معنی که میتونین در یک پروژه به راحتی از این دو زبون استفاده کنین و مزیتش اینه که اگر شما یک پروژه جاوا داشته باشین نیازی نیست که پروژه رو دور بریزین و همه چیز رو از اول بنویسین، تنها کاری که باید بکنین اینه که یک کلاس کاتلین بنویسین و از اون توابع و کلاس های جاوایی که قبلاً ساختین رو در اون استفاده کنین و همچنین یک ویژگی جالب و قشنگی که Intellij IDEA داره اینه که میتونه یک کلاس جاوا رو بگیره و اون رو به یک کلاس کاتلین تبدیل کنه. 6 | 7 | همکاری با کلاس‌های جاوا این مزیت رو بهمون میده که بتونیم از تموم کتابخانه هایی که برای JVM نوشته شده استفاده کنیم و همونطور که گفتم این مزیت رو بهمون میده که نیازی نباشه همه چیز رو از اول بنویسیم، نیازی نباشه که صبر کنیم تا یک سیستم بالابیاد و بعدش بتونیم در پروژه هامون استفاده اش کنیم. البته که خب به مراتب کاتلین با مفهوم تر و خلاصه تر و بهتر از جاواست و این به توسعه‌دهنده ها این اجازه رو میده که برای این که استفاده از یک API راحت تر بشه بیان و لایبری های کاتلین رو درست کنن که البته این کار خوبیه ولی دلیل نمیشه که نتونیم از همون کتابخونه های قبلی استفاده کنیم. 8 | 9 | البته زمانی که داریم از جاوا داخل کاتلین استفاده میکنیم باید بر طبق روند کاتلین حرکت کنیم و بلعکس اگر از کاتلین در جاوا استفاده میکنیم باید طبق روند جاوا عمل کنیم. 10 | 11 |
12 | -------------------------------------------------------------------------------- /src/introduction-to-jvm/README.md: -------------------------------------------------------------------------------- 1 |
2 | 3 | # آشنایی با JVM 4 | 5 | خب، Java Virtual Machine یک ماشین انتزائیه که برنامه های Java رو اجرا میکنه ولی این محیط از چند بخش تشکیل شده؛ به عنوان مثال برای اجرای برنامه های جاوا ما نیاز به یک محیطی داریم که بتونیم توش برنامه های جاوامون رو اجرا کنیم که اون محیط JRE و یا Java Runtime Environment نام داره همچنین برای توسعه برنامه های جاوا ما نیاز به JDK و یا Java Development Kit داریم که با این کیت بتونیم برنامه های جاوامون رو توسعه بدیم. 6 | 7 | خب به قسمتی میرسیم که ببنیم که کاتلین چگونه برنامه های خودش رو اجرا میکنه ولی قبلش باید ببینیم که جاوا چجوری یک فایل رو اجرا میکنه. 8 | 9 | اول این که ما مسلماً یک سری کد مینویسم و توی یک فایل مثلا Customer.java ذخیره میکنیم. حالا کامپایلر جاوا رو صدا میزنیم که اون کد هارو جوری کامپایل کنه که اون فایل ها قابل اجرا باشن بر روی ماشین مجازی، پس کامپایلر یک سری بایت کد درست میکنه که اون فایل ها اجرا بشن. 10 | 11 | حالا بریم سمت کاتلین: 12 | 13 | فرض میکنیم که ما میخواهیم فایل Customer.kt را اجرا کنیم.ابتدا این فایل توسط کامپایلر کاتلین به فایل Customer.Class تبدیل میشه که این فایل همون ByteCode های جاواست و این فایل همون فایلیه که توسط JVM اجرا میشه. دقت کردین که اینجا هیچگونه بار اضافه اجرایی یا به اصطلاح ( overhead ) به سیستم وارد نمیشه و عملا داریم همون بایت کد هایی رو اجرا میکنیم که اگه کدمون رو به جاوا مینوشتیم درست میشد! 14 | 15 | همون طور که گفتیم یکی از خصوصیات Kotlin اینه که باید قابلیت همکاری با Java را داشته باشد و همینطور که می بینین همینجوریه چون عملا بایت کد ها چون از یک جنس هستند میتونن با هم همکاری کنن ولی خب در بخش همکاری پذیری به این ویژگی بیشتر میپردازیم. 16 | 17 | پس یادمون باشه که نیازی به نوشتن یا تبدیل کردن پروژه های جاوامون نیست! ما میتونیم همینجوری از اون ها داخل پروژه های جدیدمون استفاده کنیم، بعله یعنی میتونید توی یک پروژه هم کاتلین کد بزنین و هم جاوا! 18 | 19 | -------------------------------------------------------------------------------- /src/kotlin-data-classes/README.md: -------------------------------------------------------------------------------- 1 |
2 | 3 | # کلاس های دیتا در کاتلین 4 | 5 | تا اینجا یاد گرفتیم چگونه یک کلاس بسازیم، چگونه خاصیت های داخل اون کلاس رو بسازیم و غیر و غیره و درواقع ما خیلی از زمان ها هست که کلاس رو میسازیم و خاصیت هارو داخلش میاریم ولی متوجه میشیم که این کلاس ها فعالیت زیادی نمیکنن، یعنی به نحوی کلاس هایی هستن که نوع دیتامون رو معرفی میکنن، Data-Object های ما هستند یا به اصطلاح توی دنیای جاوا به Java-Beans مشهور هستند. 6 | 7 | به خاطر این که کمی بیشتر اشناتون کنم بذارین یک کلاس توی جاوا بسازیم 8 | 9 |
10 | 11 | ```java 12 | public class CustomerJava { 13 | private int id; 14 | private String name; 15 | private String email; 16 | 17 | public int getId() { 18 | return id; 19 | } 20 | 21 | public void setId(int id) { 22 | this.id = id; 23 | } 24 | 25 | public String getName() { 26 | return name; 27 | } 28 | 29 | public void setName(String name) { 30 | this.name = name; 31 | } 32 | 33 | public String getEmail() { 34 | return email; 35 | } 36 | 37 | public void setEmail(String email) { 38 | this.email = email; 39 | } 40 | 41 | @Override 42 | public String toString() { 43 | return "CustomerJava{" + 44 | "id=" + id + 45 | ", name='" + name + '\'' + 46 | ", email='" + email + '\'' + 47 | '}'; 48 | } 49 | 50 | @Override 51 | public boolean equals(Object o) { 52 | if (this == o) return true; 53 | if (o == null || getClass() != o.getClass()) return false; 54 | 55 | CustomerJava that = (CustomerJava) o; 56 | 57 | if (id != that.id) return false; 58 | if (name != null ? !name.equals(that.name) : that.name != null) return false; 59 | return email != null ? email.equals(that.email) : that.email == null; 60 | } 61 | 62 | @Override 63 | public int hashCode() { 64 | int result = id; 65 | result = 31 * result + (name != null ? name.hashCode() : 0); 66 | result = 31 * result + (email != null ? email.hashCode() : 0); 67 | return result; 68 | } 69 | } 70 | ``` 71 | 72 |
73 | 74 | این یک از data-class هایی هست که داخل جاوا میسازیم، در واقع اون کسایی که با جاوا کارکردن میدونن که برای ساختن همچین کلاس هایی چه قد کد باید زده بشه، درواقع ما تنها 3 خاصیت داریم, گتر و ستر های اون و 3 تابع toString و equal و hashcode . توابعی که توی دیتا بینز هامون زیاد استفاده میکنیم. یکی از هدف های کاتلین این بوده که بتونیم کدمون رو به مراتب ساده تر و کوچیکتر بنویسیم. حالا به خاطر این که بیشتر قدر کاتلین رو بدونید همین کلاس رو توی کاتلین میسازم که متوجه بشین چه خوبی هایی این زبون داره 75 | 76 | درواقع ما getter و setter هامون رو که قبلا یادگرفتیم چجوری بنویسیم، اینجوری بود 77 | 78 |
79 | 80 | ```kotlin 81 | class CustomerKotlin(var id: Int, var name: String, var email: String) 82 | ``` 83 | 84 |
85 | 86 | همینو مینویسیم و تموم، گتر و ستر هامون آمادس. حالا بیاین و من یک main زیرش درست کنم و چند خط کد دیگه بنویسم: 87 | 88 |
89 | 90 | ```kotlin 91 | fun main(args: Array) { 92 | 93 | val customer = CustomerKotlin(1,"Sina","Sinadarvi@gmail.com") 94 | println(customer) 95 | } 96 | ``` 97 | 98 |
99 | 100 | خب ما درواقع توی کلاس CustomerJava یک تابع داشتیم به نام toString که بهمون یک چیز شسته رفته تحویل بده، همین انتظار رو از کاتلین هم داریم، یعنی گفتم اوکی کاتلین خلاصه تر میکنه ولی باید همون ویژگی های جاوا رو هم داشته باشه دیگه، خب اگه همین کد رو اجرا کنیم خواهیم دید 101 | 102 | 103 | 104 | و این هم مسلما خروجی مد نظرمون نیست. خب برای این که همچین قابلیتی رو به کلاسمون بدیم تنها کاری که باید بکنیم اینه که از کلیدواژه data استفاده کنیم 105 | 106 |
107 | 108 | ```kotlin 109 | data class CustomerKotlin(var id: Int, var name: String, var email: String) 110 | 111 | fun main(args: Array) { 112 | 113 | val customer = CustomerKotlin(1,"Sina","Sinadarvi@gmail.com") 114 | println(customer) 115 | } 116 | ``` 117 | 118 |
119 | 120 | خب حالا چی ؟ حالا اگه همین کد رو اجرا کنیم خواهیم داشت 121 | 122 | 123 | 124 | که همون چیزی هست که ما مدنظرمون داشتیم.البته این data تنها به این معنی نیست که فقط toString رو بهمون بده،درواقع hashCode و equals رو هم برامون درست میکنه. 125 | 126 | بیاین یک نکته رو اینجا نگاه کنیم: 127 | 128 | 129 |
130 | 131 | ```kotlin 132 | class CustomerKotlin(var id: Int, var name: String, var email: String) 133 | 134 | fun main(args: Array) { 135 | 136 | val customer1 = CustomerKotlin(1,"Sina","Sinadarvi@gmail.com") 137 | val customer2 = CustomerKotlin(1,"Sina","Sinadarvi@gmail.com") 138 | 139 | if(customer1 == customer2){ 140 | println("They are the same") 141 | }else{ 142 | println("they are not the same") 143 | } 144 | } 145 | ``` 146 | 147 |
148 | 149 | توجه کنین که کلید واژه data رو اینجا نداریم.خب حالا کد رو اجرا میکنیم. 150 | 151 | 152 | 153 | متوجه شدیم که این دو شبیه هم نیستن.خب حالا بیاین و data رو برگردونیم 154 | 155 |
156 | 157 | ```kotlin 158 | data class CustomerKotlin(var id: Int, var name: String, var email: String) 159 | 160 | fun main(args: Array) { 161 | 162 | val customer1 = CustomerKotlin(1,"Sina","Sinadarvi@gmail.com") 163 | val customer2 = CustomerKotlin(1,"Sina","Sinadarvi@gmail.com") 164 | 165 | if(customer1 == customer2){ 166 | println("They are the same") 167 | }else{ 168 | println("they are not the same") 169 | } 170 | } 171 | ``` 172 | 173 |
174 | 175 | و حالا اجراش کنیم 176 | 177 | 178 | 179 | همینطور که میبینین هردو به مانند هم شدن. 180 | 181 | دفعه اول وقتی دو شی رو مقایسه کردیم به دلیل متفاوت بودن آدرس خونه هاشون، دو شی برابر نبود ولی وقتی دو کلاس دیتا با هم مقایسه میشن، دیگه کامپایلر به ادرس خونشون کار نداره، محتوای کلاس رو مقایسه میکنه. 182 | 183 | کاتلین این اجازه رو میده بهمون که بتونیم از یک شی کپی بگیریم 184 | 185 |
186 | 187 | ```kotlin 188 | var customer3 = customer1 189 | var customer4 = customer1.copy() 190 | ``` 191 | 192 |
193 | 194 | در واقع شما میتونین از هر دو روش بالا استفاده کنین، یا مستقیم مقادیرش رو توی یک متغیر جدید بریزین و یا این که از تابع copy() استفاده کنید.خب البته استفاده از تابع copy() این قابلیت رو بهمون میده که بتونیم اون شی رو کپی کنیم با این تفاوت که خاصیت یا خاصیت های خاصی رو از شی اولی که داریم ازش کپی میگیریم رو تغییر بدیم. 195 | 196 |
197 | 198 | ```kotlin 199 | var customer4 = customer1.copy(email = "Sina@Darvishi.com") 200 | ``` 201 | 202 |
203 | 204 | خب البته تموم حرف هایی که زدیم به این معنی نیستش که ما فقط محدودیم که از این توابع استفاده کنیم، بلکه میتونیم data رو حذف کنیم و مثلا toString() خودمون رو بنویسیم یا این که data رو نگه داریم و toString() کاتلین رو override کنیم. 205 | 206 |
207 | 208 | ```kotlin 209 | data class CustomerKotlin(var id: Int, var name: String, var email: String){ 210 | override fun toString(): String { 211 | return "{\"id\": \"$id\", \"name\": \"$name\"}" 212 | } 213 | } 214 | ``` 215 | -------------------------------------------------------------------------------- /src/kotlin-data-classes/result-1.PNG: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/KotlinFarsi/OpenSourceTutorials-Introduction/92e9b633b82753deae74fa498e634a58c863e1d0/src/kotlin-data-classes/result-1.PNG -------------------------------------------------------------------------------- /src/kotlin-data-classes/result-2.PNG: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/KotlinFarsi/OpenSourceTutorials-Introduction/92e9b633b82753deae74fa498e634a58c863e1d0/src/kotlin-data-classes/result-2.PNG -------------------------------------------------------------------------------- /src/kotlin-data-classes/result-3.PNG: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/KotlinFarsi/OpenSourceTutorials-Introduction/92e9b633b82753deae74fa498e634a58c863e1d0/src/kotlin-data-classes/result-3.PNG -------------------------------------------------------------------------------- /src/kotlin-data-classes/result-4.PNG: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/KotlinFarsi/OpenSourceTutorials-Introduction/92e9b633b82753deae74fa498e634a58c863e1d0/src/kotlin-data-classes/result-4.PNG -------------------------------------------------------------------------------- /src/kotlin-standard-library-and-working-with-collections-in-kotlin/README.md: -------------------------------------------------------------------------------- 1 |
2 | 3 | # کتابخانه استاندارد کاتلین و کارکردن با کالکشن ها در کاتلین 4 | 5 | کاتلین به همراه یک کتابخونه استاندارد میاد که یکسری توابع و Annotation ها داره و میتونه توسعه نرم¬افزار رو برامون راحت¬تر کنه. این کتابخونه اندازه خیلی کوچیکی ( نزدیک به 800KB ) داره و سعی بر این میشه که همینطور کوچیک نگه داشته بشه.همچنین تعداد زیادی از توابع High-Order داخلش هست که برای functional-programming ارائه شده و تعداد زیادیشون درواقع توابع الحاقی هستند. کاتلین درواقع collection های خودش رو نداره! درواقع فعلا کالکشن های خودش رو نداره.(در حال حاظر که این متن ترجمه میشه، کالکشن های کاتلین موجود است)، چیزی که کاتلین داره در واقع تعدادی از interface هاست که برروی collection های جاوا ارائه شدن. 6 | 7 | 8 | 9 | که از تعدادی interface مسون و قابل تغییر تشکیل شده¬اند و این حالتی رو برامون فراهم کرده که بتونیم به صورت مسون از کالکشن¬ها استفاده کنیم. 10 | 11 | کالکشن ها از List ها، Array ها، Map ها، Set ها، HashMap ها، HashSet و خیلی چیز های دیگه تشکیل شده. 12 | 13 | خب حالا بیاین یکم کد بزنیم و کتابخونه استاندارد رو نگاه کنیم. 14 | 15 |
16 | 17 | ```kotlin 18 | fun main(args: Array) { 19 | var list: List = ArrayList() 20 | } 21 | ``` 22 | 23 |
24 | 25 | الان نمیخوایم زیاد شیرجه بزنیم توی کدزنی، فعلا یک آرایه درست کریم و مقداردهیش هم کردیم. درحال حاظر شما اگه با جاوا کارکرده باشین با ArrayList آشنا هستین، ولی چیزی که باهاش آشنا نیستین، List هه. بیاین به تعریف List رجوع کنیم. 26 | 27 | 28 | 29 | اگه کامنت¬های بالای List رو بخونین متوجه میشین که تمامی متدهای داخل این اینترفیس تنها قابل خواندن هستن و اگر بخوایم متدهایی هم قابل خواند و هم قابل نوشتن استفاده کنیم باید از اینترفیس MutableList استفاده کنیم. 30 | 31 | حالا اگه به تعریف ArrayList مراجعه کنیم متوجه میشیم که درواقع یک کلاس جاواست که یکسری متدها داره که میشه ازشون استفاده کرد و لیست رو بزرگ و کوچیک کرد. 32 | 33 | و همینطور که متوجه شدین این راه حل منطقی نیست، چراکه من دارم یک لیست از غیرمسون میسازم و اونو به لیستی میدم که مسونه! درواقع ما توی کاتلین لیست¬هامون رو اینجوری تعریف نمیکنیم و همینطور که توی جلسات قبل دیدن ما لیست هامون رو اینجوری توی کاتلین تعریف میکنیم: 34 | 35 |
36 | 37 | ```kotlin 38 | var list: List = listOf("first Entry","second Entry") 39 | ``` 40 | 41 |
42 | 43 | این listOf() چیه ؟ اگه به سمت تعریفش هدایت شین متوجه میشین که این درواقع یک تابع کمکیه که یک لیست مسون میسازه. 44 | 45 | 46 | 47 | درواقع یک emptyList() میسازه و اگه به تعریفش رجوع کنین متوجه میشین که یک لیست از Nothing هه که در نتیجه یک لیست مسون برامون ساخته. 48 | 49 | زمانی که حرف از ساختن یک کالکشن میرسه بهتره که ما تاجای ممکن از کتابخونه استاندارد استفاده کنیم. 50 | 51 | به عنوان مثال اگه بخوایم یک لیست از شماره ها درست کنیم مینوشتیم : 52 | 53 |
54 | 55 | ```kotlin 56 | val numbers = 1..10 57 | ``` 58 | 59 |
60 | 61 | و اینجا این دونقطه`..` درواقع تابع `rangeTo()` ماست، و اگه بخوایم یک لیست از شهر ها بسازیم مینوشتیم: 62 | 63 |
64 | 65 | ```kotlin 66 | val cities = listOf("Madrid","London","Paris") 67 | ``` 68 | 69 |
70 | 71 | همچنین کالکشن¬های دیگه¬ای هم هست که میشه ازشون استفاده کرد. 72 | 73 | خب بیاین یکم با این cities کار کنیم.کد زیر رو نگاه کنین: 74 | 75 |
76 | 77 | ```kotlin 78 | println(cities.javaClass) 79 | ``` 80 | 81 |
82 | 83 | درواقع اینجا javaClass میاد و تایپ اون شی رو برمیگردونه و اگه این رو اجرا کنیم نتیجه این میشه: 84 | 85 | 86 | 87 | و متوجه میشیم که درواقع داریم همون ArrayList رو استفاده میکنیم. 88 | 89 |
90 | 91 | 92 | 93 | 94 | 95 | -------------------------------------------------------------------------------- /src/kotlin-standard-library-and-working-with-collections-in-kotlin/kotlin-collection.png: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/KotlinFarsi/OpenSourceTutorials-Introduction/92e9b633b82753deae74fa498e634a58c863e1d0/src/kotlin-standard-library-and-working-with-collections-in-kotlin/kotlin-collection.png -------------------------------------------------------------------------------- /src/kotlin-standard-library-and-working-with-collections-in-kotlin/list-collection.png: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/KotlinFarsi/OpenSourceTutorials-Introduction/92e9b633b82753deae74fa498e634a58c863e1d0/src/kotlin-standard-library-and-working-with-collections-in-kotlin/list-collection.png -------------------------------------------------------------------------------- /src/kotlin-standard-library-and-working-with-collections-in-kotlin/listof-type.png: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/KotlinFarsi/OpenSourceTutorials-Introduction/92e9b633b82753deae74fa498e634a58c863e1d0/src/kotlin-standard-library-and-working-with-collections-in-kotlin/listof-type.png -------------------------------------------------------------------------------- /src/kotlin-standard-library-and-working-with-collections-in-kotlin/listof.png: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/KotlinFarsi/OpenSourceTutorials-Introduction/92e9b633b82753deae74fa498e634a58c863e1d0/src/kotlin-standard-library-and-working-with-collections-in-kotlin/listof.png -------------------------------------------------------------------------------- /src/kotlin-with-intellij-idea/README.md: -------------------------------------------------------------------------------- 1 |
2 | 3 | # کاتلین با IntelliJ IDEA 4 | 5 | خب تا اینجا یادگرفتیم چگونه با استفاده از Command line و یک Text Editor برناممون رو بنویسیم و اجرا کنیم. ولی خب ما بیشتر این دوره رو از IntelliJ IDEA استفاده میکنیم و فرقی نمیکنه که شما از نسخه رایگان یا پولی این محصول استفاده میکنید، در هر دو صورت میتونید همراه ما باشید. البته IDE های دیگری هم هستند که کاتلین رو ساپروت میکنند به مانند Eclipse,Vim,VSCode و به مانند این ها چندین IDE دیگری هستند که کاتلین رو ساپورت میکنند. 6 | 7 | IntelliJ رو باز کنید و روی Create New Project کلیک کنید. 8 | 9 | 10 | 11 | بعد از اون با صفحه ای مواجه میشید، از سمت چپ گزینه کاتلین را پیدا کرده و بر روی ان کلیک میکنیم، سپس از صفحه ای که سمت راست برامون ظاهر میشه Kotlin (JVM) رو انتخاب میکنیم. 12 | 13 | 14 | 15 | ما بعدا گزینه های maven و gradle رو هم برای ساخت برنامه های کاتلین بررسی میکنیم ولی فعلا از ورژن ساده IntelliJ استفاده میکنیم. برروی گزنه Next کلیک میکنیم. 16 | 17 | 18 | 19 | خب اسم پروژه و محل قرارگیری پروژه رو مینویسیم. من اینجا از JDK 1.8 استفاده میکنم و قسمت پایینی هم همونیه که دربارش صحبت کردیم، رانتایم کاتلین. اگه روی Create کلیک کنیم: 20 | 21 | 22 | 23 | میبینم که اینجا دو گزینه دارم یا از لایبری پلاگین شده در IntelliJ استفاده کنم و یا این که از ورژن Include شده در برنامم که بسته به نوع برنامه ای که میخواید توسعه بدید اون رو انتخاب کنید. نکته ای که هست اینکه من اینجا همینطور که میبینید از ورژن 1.1.3-2 استفاده میکنم، ترجیحا اگر نسخه جدید آن را آپدیت کنید و همراه ما باشید. 24 | 25 | خب بعد از بستن این پنجره بر روی دکمه Finish کلیک میکنم و IntelliJ فولدر مناسب رو برام میسازه. 26 | 27 | 28 | 29 | ظاهر برنامم اینجوریه که میبینید، حالا شاید به خاطر ورژن های متفاوت کاتلین و یا آپدیت های IntelliJ با ظاهری دقیقا به این شکل مواجه نشید ولی در حالت کلی به این صورت هست که میبینید. 30 | 31 | برروی فولدر src راست کلیک میکنم مسیر New>Kotlin File/Class میرم و فایل Main رو میسازم. 32 | 33 | 34 | 35 | و میبینم که فایل Main.kt در زیرشاخه src ساخته شده 36 | 37 | 38 | 39 | اگر دقت کنیم میبینیم که هیچ ساختار پکیجی اینحا مشاهده نمیکنیم، چرا که ما پکیجی برای این فایل درست نکردیم. 40 | 41 | خب اینجا من تنها کلمه main رو مینویسم و دکمه Tab رو فشار میدم و کاری که IntelliJ اینجا برامون انجام میده اینه که یک تابع Main رو برام درست میکنه. دقیقا مثل جاوا که ما اگه کلمه psvm رو مینوشتیم تابع استایک Main رو برامون درست میکرد، اینم دقیقا همون کارو برای کاتلین انجام میده. 42 | 43 | حالا اگه من کد زیر رو بنویسم: 44 | 45 |
46 | 47 | ```kotlin 48 | fun main(args: Array) { 49 | val message = "Hello From IDEA!" 50 | println(message) 51 | } 52 | ``` 53 | 54 |
55 | 56 | حالا میتونیم پروژه رو ران کنیم و نتیجه رو ببینیم. 57 | 58 | 59 | 60 | من همچنین میتونم دیباگ کنم.روی یک خط از برنامه با کلیک کردن روی نوار کناری علامت میذارم و دوباره روی شکلک کاتلین کلیک میکنم و این دفعه گزینه دیباگ رو میزنم. 61 | 62 | 63 | 64 | بنابراین استفاده از IntelliJ این امکان رو میده که ما بتونیم برناممون رو کامپایل،اجرا دیباگ و خیلی کار های دیگه روش انجام بدین. ضمنا یادتون نره که Kotlin توسط همین شرکتی که IntelliJ رو ساخته درست شده و مطمئن باشید اگه قرار باشه ویژگی خاصی رو در کاتلین ببنین اولین بار با استفاده از IntelliJ اونو خواهید دید. 65 | 66 |
67 | -------------------------------------------------------------------------------- /src/kotlin-with-intellij-idea/compiled-application.PNG: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/KotlinFarsi/OpenSourceTutorials-Introduction/92e9b633b82753deae74fa498e634a58c863e1d0/src/kotlin-with-intellij-idea/compiled-application.PNG -------------------------------------------------------------------------------- /src/kotlin-with-intellij-idea/create-main.PNG: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/KotlinFarsi/OpenSourceTutorials-Introduction/92e9b633b82753deae74fa498e634a58c863e1d0/src/kotlin-with-intellij-idea/create-main.PNG -------------------------------------------------------------------------------- /src/kotlin-with-intellij-idea/debug-application.PNG: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/KotlinFarsi/OpenSourceTutorials-Introduction/92e9b633b82753deae74fa498e634a58c863e1d0/src/kotlin-with-intellij-idea/debug-application.PNG -------------------------------------------------------------------------------- /src/kotlin-with-intellij-idea/new-project-1.PNG: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/KotlinFarsi/OpenSourceTutorials-Introduction/92e9b633b82753deae74fa498e634a58c863e1d0/src/kotlin-with-intellij-idea/new-project-1.PNG -------------------------------------------------------------------------------- /src/kotlin-with-intellij-idea/new-project-2.PNG: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/KotlinFarsi/OpenSourceTutorials-Introduction/92e9b633b82753deae74fa498e634a58c863e1d0/src/kotlin-with-intellij-idea/new-project-2.PNG -------------------------------------------------------------------------------- /src/kotlin-with-intellij-idea/new-project-3.PNG: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/KotlinFarsi/OpenSourceTutorials-Introduction/92e9b633b82753deae74fa498e634a58c863e1d0/src/kotlin-with-intellij-idea/new-project-3.PNG -------------------------------------------------------------------------------- /src/kotlin-with-intellij-idea/view-of-first-application.PNG: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/KotlinFarsi/OpenSourceTutorials-Introduction/92e9b633b82753deae74fa498e634a58c863e1d0/src/kotlin-with-intellij-idea/view-of-first-application.PNG -------------------------------------------------------------------------------- /src/kotlin-with-intellij-idea/view-of-main.PNG: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/KotlinFarsi/OpenSourceTutorials-Introduction/92e9b633b82753deae74fa498e634a58c863e1d0/src/kotlin-with-intellij-idea/view-of-main.PNG -------------------------------------------------------------------------------- /src/kotlin-with-intellij-idea/welcome-to-intellij-idea.PNG: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/KotlinFarsi/OpenSourceTutorials-Introduction/92e9b633b82753deae74fa498e634a58c863e1d0/src/kotlin-with-intellij-idea/welcome-to-intellij-idea.PNG -------------------------------------------------------------------------------- /src/lambda-expressions-in-kotlin/README.md: -------------------------------------------------------------------------------- 1 |
2 | 3 | # عبارت های لاندا در کاتلین 4 | 5 | تا الان دیدیم وقتی تابع operation ای که جلسه پیش ساختیم رو میخواستیم استفاده کنیم تابع sum رو با صدا زدن نامش استفاده می کردیم ولی آیا واقعا لازمه که تابع رو حتما بسازیم و بعد نامش رو صدا بزنیم؟ چرا نتونیم تابع رو داخل بدنه تابع دیگه بسازیم؟ اینجاست که ما از عبارت های Lambda استفاده میکنیم. 6 | 7 | کد زیر رو نگاه کنین: 8 | 9 |
10 | 11 | ```kotlin 12 | fun operation(x: Int, y: Int,op: (Int,Int)->Int): Int { 13 | return op(x,y) 14 | } 15 | 16 | fun sum(x: Int, y: Int) = x + y 17 | 18 | fun main(args: Array) { 19 | 20 | println(operation(2, 3, ::sum)) 21 | println(operation(2, 3, { x, y -> x + y })) 22 | } 23 | ``` 24 | 25 |
26 | 27 | دو عبارت بالا یک عمل رو انجام میدن. اگه دقت کنین ما تایپ x و y رو توی بدنه مشخص نکردیم، درواقع کاتلین خودش متوجه میشه که چون داریم دو عبارت 2 و 3 رو به این تابع میدید پس باید x و y از جنس Int باشن! کاتلین خودش متوجه میشه که چه تایپی رو باید به x و y بده! مثلا اگه همین عبارت رو میخواستیم بنویسیم باید اینجوری مینوشیتم: 28 | 29 |
30 | 31 | 32 | ```kotlin 33 | fun operation(x: Int, y: Int,op: (Int,Int)->Int): Int { 34 | return op(x,y) 35 | } 36 | 37 | fun sum(x: Int, y: Int) = x + y 38 | 39 | fun main(args: Array) { 40 | 41 | val LambdaSum: (Int, Int) -> Int = { x, y -> x + y } 42 | println(operation(2, 3, LambdaSum)) 43 | 44 | } 45 | ``` 46 | 47 |
48 | 49 | و دقت کنین که در اینصورت باید تایپ x و y رو مشخص میکردیم! 50 | 51 | خب حالا یک تابع High-Order دیگه بسازیم 52 | 53 |
54 | 55 | ```kotlin 56 | fun unaryOperation(x:Int,op: (Int) -> Int){ 57 | 58 | } 59 | 60 | fun main(args: Array) { 61 | unaryOperation(2, { x -> x * x }) 62 | } 63 | ``` 64 | 65 |
66 | 67 | توی کاتلین به مانند زبون Groovy ، اگر عبارت Lambda تنها یک پارامتر داشته باشه، لازم نیست که ما دقیق بیان کنیم چی رو داریم صدا میزنیم، کافیه از کلیدواژه “it” استفاده کنیم: 68 | 69 |
70 | 71 | ```kotlin 72 | fun unaryOperation(x:Int,op: (Int) -> Int){ 73 | 74 | } 75 | 76 | fun main(args: Array) { 77 | unaryOperation(2, { it * it }) 78 | } 79 | ``` 80 | 81 |
82 | 83 | در واقع ما توی کاتلین میتونیم تابع High-Order رو ساده تر و هم به صورت منظم تری بنویسیم. توی کاتلین اگر تابع به عنوان اخرین پارامتر به یک تابع High-Order پاس داده بشه میشه اون رو به صورت دیگه ای هم نوشت. مثلا کد بالا رو میتونیم اینجوری هم بنویسیم: 84 | 85 |
86 | 87 | ```kotlin 88 | fun unaryOperation(x:Int,op: (Int) -> Int){ 89 | 90 | } 91 | 92 | fun main(args: Array) { 93 | unaryOperation(2, { it * it }) 94 | unaryOperation(2) { 95 | it * it 96 | } 97 | } 98 | ``` 99 | 100 |
101 | 102 | ممکنه شما بگین خب این کجا ممکنه به درد بخوره؟ خب بذارین توی یک مثال بهتون تفاوت و قشنگیه سینتکس کاتلین رو نشون بدم. 103 | 104 | بیاین یک کلاس بسازیم به نام Database و اون کلاس هم یک تابع داشته باشه به نام commit ، لازم هم نیست بدنه تابع commit رو هم بنویسیم. 105 | 106 |
107 | 108 | ```kotlin 109 | class Database { 110 | fun commit(){ 111 | } 112 | } 113 | ``` 114 | 115 |
116 | 117 | حالا خارج کلاس، تابع دیگه ای بنویسیم به نام transaction که یک Database و یک سری کد رو به عنوان ورودی میگیره: 118 | 119 |
120 | 121 | ```kotlin 122 | class Database { 123 | fun commit(){ 124 | } 125 | } 126 | 127 | fun transaction(db: Database, code: () -> Unit ){ 128 | try { 129 | code() 130 | } finally { 131 | db.commit() 132 | } 133 | } 134 | ``` 135 | 136 |
137 | 138 | و تنها کاری که میکنه اینه که code رو روی database اجرا میکنه و در انتها اون دیتابیس رو هم commit میکنه. 139 | 140 | حالا کافیه که اینجوری ازش استفاده کنیم: 141 | 142 |
143 | 144 | ```kotlin 145 | class Database { 146 | fun commit(){ 147 | } 148 | } 149 | 150 | fun transaction(db: Database, code: () -> Unit ){ 151 | try { 152 | code() 153 | } finally { 154 | db.commit() 155 | } 156 | } 157 | 158 | fun main(args: Array) { 159 | val db = Database() 160 | transaction(db){ 161 | //interact with database 162 | } 163 | } 164 | ``` 165 | 166 |
167 | 168 | خیلی قشنگ اومدیم یک متغیر دیتابیس درست کردیم و به تابع transaction دادیم که این تابع میاد اون کد هایی که داخل براکت هامون نوشتیم رو اجرا میکنه و در انتها هم دیتابیس رو commit میکنه. 169 | 170 | یکی دیگه از روش های ساختن یک تابع High-Order در کاتلین، استفاده از توابع بی نام است. 171 | 172 |
173 | 174 | ```kotlin 175 | fun unaryOperation(x:Int,op: (Int) -> Int){ 176 | 177 | } 178 | fun main(args: Array) { 179 | unaryOperation(2, fun(x: Int): Int { return x * x }) 180 | } 181 | ``` 182 | 183 |
184 | 185 | در واقع همونطور که از نامش مشخصه تابعی رو ساختیم که نام نداره. خب ممکنه بپرسین که کجا ممکنه این بدردمون بخوره ؟ برای شروع باید بگم جایی که لازم نباشه تایپ مقدار بازگشتی رو مشخص کنین و یا جایی که دلتون بخواد چندین نقطه داشته باشین که بر حسب شرایط یک مقدار متفاوت رو برگردونن. 186 | 187 |
188 | -------------------------------------------------------------------------------- /src/lambda-expressions-in-kotlin/result-1.PNG: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/KotlinFarsi/OpenSourceTutorials-Introduction/92e9b633b82753deae74fa498e634a58c863e1d0/src/lambda-expressions-in-kotlin/result-1.PNG -------------------------------------------------------------------------------- /src/loops-and-ranges-in-kotlin/README.md: -------------------------------------------------------------------------------- 1 |
2 | 3 | # حلقه ها در کاتلین 4 | 5 | حالا بیاین یکم نگاه حلقه ها کنیم، 6 | 7 | یک فایل دیگه به نام `LoopsAndRanges` درست میکنیم و `main` رو داخلش مینویسیم 8 | 9 | 10 | 11 | 12 | اگه دقت کنیم داخل این فایل هم `main` داریم و داخل فایل قبلی هم `main` داریم. ایا همچین چیزی ممکن است؟ درواقع کاتلین همیچین اجازه رو میده که به ازای هر فایل یک `main` داشته باشیم. 13 | 14 | خب حالا از این قضیه بگذریم، بیاین یک حلقه `for` درست کنیم 15 | 16 |
17 | 18 | ```kotlin 19 | for(a:Int in 1..100){ 20 | println(a) 21 | } 22 | ``` 23 | 24 |
25 | 26 | 27 | ابتدا نام یک متغیر رو تعریف میکنیم که میخوایم بر روی اون راه بریم. سپس تایپش رو معرفی میکنیم سپس با استفاده از کلید واژه `in` میگیم که میخوایم در چه محدوده ای(هرچی جلوش میاد) راه بریم و بعدش محدوده رو تعریف میکنیم و در انتها هم هرچی جلوی اکولاد ها میاد رو هر دفعه انجام میده. در واقع ما اینجا هم میتونیم تایپ رو مشخص نکنیم و خود کامپایلر میفهمه منظورمون کدوم تایپه. 28 | نکته ای که در اینجا باید توجه کنیم بهش اینه که اون `..` که اومده درواقع همان تابع `rangeTo()` است. در واقع ما میتونیم اینجور بنویسیم: 29 | 30 |
31 | 32 | ```kotlin 33 | val numbers = 1..100 34 | ``` 35 | 36 |
37 | 38 | که درواقع داریم یک لیست درست میکنیم از اعداد 1 تا 100 . و اگه بخوام یک حلقه `for` درست کنیم میتونیم از همین `numbers` استفاده کنیم 39 | 40 |
41 | 42 | ```kotlin 43 | for(a in numbers){ 44 | print(a) 45 | } 46 | ``` 47 | 48 |
49 | 50 | حالا اگه بخوایم یک حلقه برعکس بنویسیم میتونیم به این روش انجام بدیم 51 | 52 |
53 | 54 | ```kotlin 55 | for(a in 100 downTo 1){ 56 | println(a) 57 | } 58 | 59 | for(a in 100..1){ 60 | println(a) 61 | } 62 | ``` 63 | 64 |
65 | 66 | حالا فرض کنید میخوایم از 100 تا 1 پایین بیایم ولی 5 تا 5 تا : 67 | 68 |
69 | 70 | ```kotlin 71 | for(b in 100..1 step 5){ 72 | println(b) 73 | } 74 | ``` 75 | 76 |
77 | 78 | ولی خب این تنها یک حلقه برروی شماره ها بود، کاتلین این اجازه رو میده که برروی دسته ها هم راه برید. مثلا کد زیر رو در نظر بگیرین 79 | 80 |
81 | 82 | ```kotlin 83 | val capitals = listOf("London","Paris","Rome","Madrid") 84 | for(capital in capitals){ 85 | println(capital) 86 | } 87 | ``` 88 | 89 |
90 | 91 | حالا کار نداشته باشین اون listOf چیه و چگونه کار میکنه فعلا فقط بدونین که یک لیست درست میکنه. به همین راحتی این لیست رو به for میدیم و اون روی این لیست راه میره و تموم اون مرکز شهر هارو چاپ میکنه. 92 | 93 | خب حلقه ها تنها for نیستند، مثلا while و do while نیز به صورت زیر نوشته میشوند 94 | 95 |
96 | 97 | ```kotlin 98 | var i = 100 99 | while (i>0){ 100 | i-- 101 | } 102 | var x = 10 103 | do { 104 | x-- 105 | }while (x>0) 106 | ``` 107 | 108 |
109 | 110 | حالا خارج از بحث حلقه ها، کاتلین این ویژگی را به کاربر میدهد که بتواند حلقه را ادامه دهد یا از حلقه بیرون بیایید. به عنوان مثال به تکه کد زیر دقت کنید: 111 | 112 |
113 | 114 | ```kotlin 115 | loop@ for (i in 1..100){ 116 | for(j in 1..100){ 117 | if(i%j == 0) 118 | break@loop 119 | } 120 | } 121 | ``` 122 | 123 |
124 | 125 | در اینجا ما با هدف قرار دادن حلقه اول از حلقه دوم خارج میشویم به این صورت که وقتی break را مینویسم با یک @ یک لیبل را مشخص میکنیم که میخواهیم به ان وارد شویم. و همینطور با continue 126 | 127 |
128 | 129 | ```kotlin 130 | loop@ for (i in 1..100){ 131 | for(j in 1..100){ 132 | if(i%j == 0) 133 | continue 134 | } 135 | } 136 | ``` 137 | 138 | 139 | 140 | 141 | 142 | 143 | -------------------------------------------------------------------------------- /src/loops-and-ranges-in-kotlin/view-of-class.PNG: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/KotlinFarsi/OpenSourceTutorials-Introduction/92e9b633b82753deae74fa498e634a58c863e1d0/src/loops-and-ranges-in-kotlin/view-of-class.PNG -------------------------------------------------------------------------------- /src/member-functions-in-kotlin/README.md: -------------------------------------------------------------------------------- 1 |
2 | 3 | # توابعِ عضو در کاتلین 4 | 5 | 6 | ما دیدیم که چگونه یه تابع Top-Level بسازیم، اما به هرحال کاتلین یه زبون شی گراست و بنابراین باید بتونیم داخل کلاس هم تابع بنویسیم که به این تابع ها Member-Functions میگن. 7 | 8 | ولی خب تعریف تابع داخل کلاس خیلی راه حل سر راستی داره، به همون راحتی که قبلا توی یک فایل تابع مینوشیتم، مثلا کد زیر رو نگاه کنین 9 | 10 |
11 | 12 | ```kotlin 13 | class Customer(var id: Int, var name: String, var yearOfBirth: Int){ 14 | 15 | fun customerAsString(){ 16 | println("id : $id - name : $name") 17 | } 18 | } 19 | ``` 20 | 21 |
22 | 23 | که تابعمون دو خاصیت رو از کلاسمون چاپ میکنه. 24 | 25 | برای استفاده ازش هم کافیه از شی که از کلاسمون ساختیم تابع رو صدا بزنیم 26 | 27 |
28 | 29 | ```kotlin 30 | fun main(args: Array) { 31 | var customer = Customer(10, "Sina",1995) 32 | 33 | customer.customerAsString() 34 | } 35 | ``` 36 | -------------------------------------------------------------------------------- /src/null-safety-and-summary/README.md: -------------------------------------------------------------------------------- 1 |
2 | 3 | # null safety و خلاصه بخش هفت 4 | 5 | مطمئنم تا الان اسم خطای میلیارد دلاری رو شنیدین که مبحث Null هارو پیش میاره. مقالات خیلی زیادی در این مورد ارائه شده که به زبان هایی اشاره دارن که از Null ها ساپورت میکنن و در زمان اجرا به NullPointerException میخورن. 6 | 7 | به صورت پیشفرض کاتلین Null Safe است. این به چه معنیه؟ بیاین یکم کد بزنیم تا متوجه بشیم 8 | 9 |
10 | 11 | ```kotlin 12 | fun main(args: Array) { 13 | val message = "A String" 14 | 15 | println(message.length) 16 | } 17 | ``` 18 | 19 |
20 | 21 | یک رشته ساختیم به نام message و داخلش یک مقدار ریختیم. حالا طول message رو پرینت میکنیم. مطمئنم هیچ وقت به مشکل برنمیخوریم! چرا که هیچ وقت message تهی یا Null نخواهد بود.چرا ؟ چون خب مقدار دهی کردیمش. بیاین یکم واضح درمورد message صحبت کنیم و دقیق تایپش رو بنویسیم. بعدش مقدار جلوش رو پاک کنیم و مقدار null رو جایگزینش کنیم. 22 | 23 |
24 | 25 | ```kotlin 26 | fun main(args: Array) { 27 | val message :String = null 28 | 29 | println(message.length) 30 | } 31 | ``` 32 | 33 |
34 | 35 | متوجه میشیم که کامپایلر بهمون ارور میده! چراکه در کاتلین به صورت پیشفرض تایپ ها امکان null بودن نخواهند داشت برای اینه که میگیم کاتلین یک زبون Null Safe هست! پس زمانی که یک متغیر رو معرفی میکنی Null نخواهد بود و این اطمینان رو بهمون میده که وقتی از message.length استفاده میکنیم هیچ وقت به NullRefrence نخواهیم خورد. 36 | 37 | ولی زمانی که ما خودمون بخوایم از Null استفاده کنیم چی؟ به هرحال دلیلی ممکنه پیش بیاد که ما بخوایم با null ها کار کنیم مثلا یک چیزی که ما خیلی ذکر کردیم اینه که کاتلین میتونه به راحتی با جاوا ارتباط داشته باشه و همکاری کنه! خب توی جاوا هم null ها هستن، اگر کلاس جاوامون به کلاس کاتلینمون null داد چی؟ 38 | 39 | در واقع ما میتونیم متغیر هایی تعریف کنیم که مقدار null رو بپذیرن و تعریفشون هم با استفاده از "?" انجام میگیره 40 | 41 |
42 | 43 | ```kotlin 44 | fun main(args: Array) { 45 | // val message :String = null 46 | val nullMessage :String? = null 47 | 48 | // println(message.length) 49 | } 50 | ``` 51 | 52 |
53 | 54 | همچنین میتونیم اصلا تایپش رو ذکر نکنیم و کامپایلر خودش فرض کنه این متغیر میتونه null باشه 55 | 56 |
57 | 58 | ```kotlin 59 | fun main(args: Array) { 60 | // val message :String = null 61 | // val nullMessage :String? = null 62 | val inferredNullMessage = null 63 | 64 | // println(message.length) 65 | } 66 | ``` 67 | 68 |
69 | 70 | خب حالا ایا ما خاصیت NullSafety رو از کاتلین از بین بردیم؟ بیاین این کد رو اجرا کنین: 71 | 72 |
73 | 74 | ```kotlin 75 | fun main(args: Array) { 76 | // val message :String = null 77 | val nullMessage :String? = null 78 | // val inferredNullMessage = null 79 | 80 | // println(message.length) 81 | println(nullMessage.length) 82 | 83 | } 84 | ``` 85 | 86 |
87 | 88 | متوجه میشیم که کامپایلر بازم ارور میده، کامپایلر میگه ممکنه این متغییر به Null بخوره، پس من اجازه نمیدم اجراشه! 89 | 90 | خب درواقع کاری که قبلا میکردیم این بود که یک شرط قبل اجرا میذاشتیم که اگه اون مقدار null بود فلان کار رو انجام نده.الانم همین کارو میتونیم انجام بدیم 91 | 92 |
93 | 94 | ```kotlin 95 | fun main(args: Array) { 96 | // val message :String = null 97 | val nullMessage :String? = null 98 | // val inferredNullMessage = null 99 | 100 | // println(message.length) 101 | if(nullMessage != null) 102 | println(nullMessage.length) 103 | } 104 | ``` 105 | 106 |
107 | 108 | و کامپایلر متوجه میشه که شما قبلش دارین چک میکنین که null هست یا نه و اجازه میده که این برنامه اجرا شه. ولی خب برگشتیم سر خونه اول! الان یک متغیر داریم که میتونه null باشه و هرجا میخوایم ازش استفاده کنیم چک میکنم که ایا null هست یا نه و حالا بعضی مواقع هم پیش میاد که نیاز باشه قبل از این که یک متغیر رو چک کنیم که null هست یا، لازم باشه متغیر های قبل از اونو هم چک کنیم و اون موقع است که کلی if تو در تو داریم. 109 | 110 | کاتلین میاد یک اپراتوری معرفی میکنه به شکل "؟" که خودش میاد میگه "اگر" مقدار این متغیر برابر null نبود عمل رو انجام بده و اگر برابر null بود از روش عبور کن. مثلا عبارت بالامون رو تنها کافیه اینجوری بنویسیم: 111 | 112 |
113 | 114 | ```kotlin 115 | fun main(args: Array) { 116 | // val message :String = null 117 | val nullMessage :String? = null 118 | // val inferredNullMessage = null 119 | 120 | // println(message.length) 121 | println(nullMessage?.length) 122 | } 123 | ``` 124 | 125 |
126 | 127 | و ارورمون هم اینجا از بین میره حتی! 128 | 129 | البته اگه کد بالا رو اجرا کنیم جواب زیر رو خواهیم داشت 130 | 131 | 132 | 133 | چیزی که اینجا میبینین اینه که null چاپ شد، خب پس چرا null چاپ شد؟ 134 | 135 | در واقع println یک null رو میگیره و تبدیلش میکنه به یک رشته با محتوای null و این خوبه، چراکه حداقل null رو چاپ میکنه! 136 | 137 | البته یک روش خطرناک دیگه هم هست برای اینکه بدون "؟" بخوایم یک متغییر null رو چاپ کنیم یا به مانند این با یک متغیر null عملی رو انجام بدیم. واونم اینه که از عملگر "!!" استفاده کنیم، یعنی 138 | 139 |
140 | 141 | ```kotlin 142 | fun main(args: Array) { 143 | 144 | val nullMessage = null 145 | 146 | println(nullMessage!!.length) 147 | } 148 | ``` 149 | 150 |
151 | 152 | ولی وقتی این رو اجرا کنیم متوجه میشیم که برنامه به ارور میخوره !! نه ارور قبل کامپایل نه! بلکه ارور در زمان اجرا! همون ارور ها که باعث ضرر ملیون دلاری میشه! 153 | 154 | خب چرا ؟ مگه ما نگفتیم کاتلینن NullSafe هستش ؟ جواب اینه که اینجا ایرادی به کاتلین و کامپایلرش نیست، بلکه ایراد به ما و توسعه دهنده هاست، درواقع ما با اضافه کردن اوپراتور "!!" به کامپایلر میگیم " من میدونم دارم چیکار میکنم، بذار کار خودم رو انجام بدم" و کامپایلر هم میذاره روند کامپایل و اجرای برنامه پیش بره ولی اگر اینجا به مشکل خورد مشکل خودتونه. البته سوالی هم هست که چرا ما بخوایم همچین کاری کنیم؟ درواقع زمان هایی هست مخصوصا زمانی که بحث ارتباط با جاوا پیش بیاد و این منطقی میشه که صریحا به کامپایلر بگیم نیازی به نگران شدنت نداریم، من میدونم دارم چیکار میکنم. 155 | 156 | **خلاصه بخش 7:** 157 | 158 | 1- کاتلین به صورت پیشفرض یک زبان Null Safe هستش 159 | 160 | 2- شما میتونین متغیر هایی داشته باشین که صریحا بیان کنن که میتونن null باشن، ما این کار رو با ? انجام میدیم 161 | 162 | 3- عملگر ؟ به ما این قدرت رو میده که بتونیم به متغیر ها زمانی که null نیستند دسترسی داشته باشیم 163 | 164 | 4- عملگر !! این اجازه رو میده که بدون این که چک کنیم این متغیر null هست یا نه به اون متغیر دسترسی داشته باشیم 165 | 166 | 167 |
168 | 169 | 170 | -------------------------------------------------------------------------------- /src/null-safety-and-summary/result-1.PNG: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/KotlinFarsi/OpenSourceTutorials-Introduction/92e9b633b82753deae74fa498e634a58c863e1d0/src/null-safety-and-summary/result-1.PNG -------------------------------------------------------------------------------- /src/objects-in-kotlin-and-summary/README.md: -------------------------------------------------------------------------------- 1 |
2 | 3 | # Object ها در کاتلین و خلاصه بخش پنج 4 | 5 | نمیدونم که آیا تفاوت کلاس و Object رو میدونید یا نه؟ واسه همین یه توضیح کوچولو میدم. 6 | 7 | واضح ترین تفاوت میان این دو اینه که کلاس به مانند یک نقشه برای طراحی ساختمون میمونه، یعنی در واقع شما با ساختن یک کلاس یک، نمونه میسازین که اشیاء ارث بری شده ازشون میتونن کار های دلخواهتون رو انجام بدن. ولی به عنوان مثال در JavaScript کلاس تعریف نشدس و به جای اون Object هایی ساخته میشن که میتونن 2 کار رو انجام بدن، یا به صورت یک نمونه برای Object های دیگه عمل کنن و یا خودشون همون اعمال رو انجام بدن. 8 | 9 | در کاتلین شما هم تعریفی به نام Object داری و هم تعریفی به نام Class و خب در نتیجه مواقعی که لازمه میتونید از Object استفاده کنید مخصوصا مواقعی که میخواین Functional کد بنویسین. 10 | 11 | خب حالا بیاین ببینیم چجوری: 12 | 13 |
14 | 15 | ```kotlin 16 | object Global{ 17 | val PI = 3.14 18 | } 19 | 20 | fun main(args: Array) { 21 | println(Global.PI) 22 | } 23 | ``` 24 | 25 |
26 | 27 | به همین سادگی که میبینین. من حتی میتونم همین object رو به صورت یک عبارت بیان کنم. 28 | 29 |
30 | 31 | ```kotlin 32 | object Global{ 33 | val PI = 3.14 34 | } 35 | 36 | fun main(args: Array) { 37 | val localObject = object { 38 | val PI = 3.14159 39 | } 40 | 41 | println(localObject.PI) 42 | println(Global.PI) 43 | } 44 | ``` 45 |
46 | 47 | تفاوتی که این دو دارن اینه که عبارت ها سریعا ساخته میشن! خب البته درمورد استفاده های Object بعدا بیشتر صحبت میکنیم. 48 | 49 | **خلاصه بخش 5:** 50 | 51 | 1- کلاس ها به مانند شهروند رتبه اول در کاتلین به حساب میان( به مانند Top-level-functions) 52 | 53 | 2- میتونن خصیصه و توابع داخل خودشون داشته باشن 54 | 55 | 3- توی کاتلین چیزی به نام feild وجود نداره( البته منظورمون متغییر های feild هستش و نه اون که توی بخش کلاس های دیتا دیدیم) 56 | 57 | 4- با کلاس های دیتا اشنا شدیم 58 | 59 | 5- با enum ها اشنا شدیم 60 | 61 | 6- Object ها یک روش خیلی ساده برای ساختن singleton ها هستند 62 | 63 | 64 |
65 | -------------------------------------------------------------------------------- /src/package-and-imports-in-kotlin-and-summary-of-kotlin-basic/README.md: -------------------------------------------------------------------------------- 1 |
2 | 3 | # اضافه کردن پگیج ها در کاتلین و خلاصه بخض سوم 4 | 5 | خب ¬¬¬اگه تموم مثال هایی که زدیم رو دیده باشین متوجه شدین که ما تقریبا به یک پکیج محدود بودیم و ما داخل اون پکیج کار میکردیم.مثلا اکه همون فایل Main که دفعه اول استفاده کردیم رو نگاه کنیم متوجه خواهیم شد که ما از تابعی به نام println() استفاده کردیم . این تابع از کجا آمد؟ چجوری ازش استفاده کردیم ؟ 6 | 7 | اگه روی ویندوز هستید و دکمه Ctrl رو نگه دارید و روی تابع کلیک کنین به سمت تعریف اون تابع هدایت میشین. و اگر به ابتدای اون فایل برین متوجه میشین که این تابع داخل بسته ای به نام kotlin.ioهستش. پکیج ها به مانند جاوا و دیگر زبون ها میتونن import بشن ولی در واقع نیازی به import کردن توابعی مثل println() و به مانند این ها نیست، در واقع اونها به طور ضمنی import شدن ولی من میتونم پکیج های دیگه رو از جاهای دیگه ی برنامم import کنم. به عنوان مثال بیاین و داخل همون پکیج basic یک پکیج دیگه به نام utils باز کنیم. و داخل اون هم یک فایل به نام SampleUtils باز کنیم. 8 | 9 | 10 | 11 | حالا بیایم و یک تابع به نام SomeUtility() در اون باز کنیم که یک متغییر name از جنس String میگیره. 12 | 13 | خب حالا اگر به فایل Main برگردم میتونم با استفاده از کلیدواژه import ابتدا فایل SampleUtils رو اضافه کنم و بعدش از توابع داخلش استفاده کنم. توجه کنین که اگر هم ابتدا اون فایل رو import نکنم و مستقیم بنویسم SomeUtility خود intelliJ برام فایل رو import میکنه و یا از من سوال میپرسه که import اش کنم یا نه. 14 | 15 | 16 |
17 | 18 | ```kotlin 19 | package com.kotlinfarsi.introduction.basics 20 | 21 | import com.kotlinfarsi.introduction.basics.utils.someUtility 22 | 23 | fun main(args: Array) { 24 | println("Hello World!") 25 | 26 | someUtility("Some Name") 27 | } 28 | ``` 29 | 30 |
31 | 32 | ما میتونیم به جای این که مشخص کنیم از چه فایلی میخوایم دقیقا استفاده کنیم بگیم از کل فایل های داخل این پکیج استفاده کن و اون رو با گذاشتن * به جای someUtility انجام میدیم. 33 | 34 |
35 | 36 | ```kotlin 37 | import com.kotlinfarsi.introduction.basics.utils.* 38 | ``` 39 | 40 |
41 | 42 | همچنین اومدیم و فایل رو import کردیم و متوجه شدیم فایلی که import شده هم نام با یکی از فایل های دیگمونه،میتونیم به این روش جور دیگه ای ازش استفاده کنیم 43 | 44 |
45 | 46 | ```kotlin 47 | package com.kotlinfarsi.introduction.basics 48 | 49 | import com.kotlinfarsi.introduction.basics.utils.someUtility as someAditionalFunctions 50 | 51 | fun main(args: Array) { 52 | println("Hello World!") 53 | 54 | someAditionalFunctions("Some Name") 55 | } 56 | ``` 57 | 58 |
59 | 60 | ## خلاصه بخش 3 61 | 62 | * تا اینجا یاد گرفتیم که چگونه یک متغیر رو تغییرپذیر یا تغییر ناپذیر کنیم 63 | 64 | * با حلقه for اشنا شدیم و فهمیدیم میتونه روی یک کالکشن هم راه بره 65 | 66 | * و همچنین یاد گرفتیم که if و when میتونن به صورت یک عبارت منطقی به عنوان نتیجه برای یک متغییر استفاده بشه 67 | 68 | -------------------------------------------------------------------------------- /src/package-and-imports-in-kotlin-and-summary-of-kotlin-basic/someutils.PNG: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/KotlinFarsi/OpenSourceTutorials-Introduction/92e9b633b82753deae74fa498e634a58c863e1d0/src/package-and-imports-in-kotlin-and-summary-of-kotlin-basic/someutils.PNG -------------------------------------------------------------------------------- /src/talking-to-java-from-kotlin/README.md: -------------------------------------------------------------------------------- 1 |
2 | 3 | # صحبت کردن با جاوا از کاتلین 4 | 5 | برای تمرین این قسمت بهتر است از IntelliJ IDEA استفاده شود 6 | 7 | خب بیاین در داخل کاتلین با جاوا صحبت کنیم. توجه داشتین که یک کلاس CustomerJava داشتیم که در واقع یک Java Bean بود.خب حالا بیاین توی یک کلاس کاتلین از این کلاس جاوا یک متغیر بسازیم و بعد به یک خصیصه از اون کلاس جاوا دسترسی داشته باشم 8 | 9 |
10 | 11 | ```kotlin 12 | fun main(args: Array) { 13 | val customer = CustomerJava() 14 | println(customer.email) 15 | } 16 | ``` 17 | 18 |
19 | 20 | اگه دقت کنین برای استفاده از email نیازی نیست که تابع getEmail رو صدا بزنیم! تنها کاری که لازمه اینه که نام اون متغیر رو صدا بزنیم و کاتلین خودش حدس میزنه که به چی نیاز داریم. البته به این معنی نیست که تابع getEmail رو نداریم و در واقع اگه بخوایم میتونیم از این تابع استفاده کنیم ولی خود کاتلین این اجازه رو میده که نیازی به صدا کردن تابع برای خوندن مقدارش نداشته باشیم. این ویژگی مسلما برای set هم هست و هر موقع بخوایم مقدار جدیدی رو بدیم کافیه همین روش رو به کار ببریم. 21 | 22 | درمورد ارث بری هم روند کارمون سادست. بیایی یک کلاس به نام PersonJava در کد جاوامون ایجاد کنیم: 23 | 24 |
25 | 26 | ```java 27 | public class PersonJava { 28 | private int id; 29 | 30 | public int getId() { 31 | return id; 32 | } 33 | 34 | public void setId(int id) { 35 | this.id = id; 36 | } 37 | } 38 | ``` 39 | 40 |
41 | 42 | و حالا بیاین از این ارثبری کنیم: 43 | 44 |
45 | 46 | ```kotlin 47 | class PersonKotlin : PersonJava() 48 | ``` 49 | 50 |
51 | 52 | به این راحتی از یک کلاس جاوا ارثبری کردیم. این قضیه حتی برای Interface ها هم برقراره 53 | 54 |
55 | 56 | ```java 57 | public interface CustomerRepository { 58 | CustomerJava getById(int id); 59 | List getAll(); 60 | } 61 | ``` 62 | 63 |
64 | 65 | و حالا میتونم داخل کاتلین از این Interface استفاده کنیم 66 | 67 |
68 | 69 | ```kotlin 70 | class KotlinCustomerRepo : CustomerRepository{ 71 | override fun getAll(): MutableList { 72 | TODO("not implemented") 73 | } 74 | 75 | override fun getById(id: Int): CustomerJava { 76 | TODO("not implemented") 77 | } 78 | } 79 | ``` 80 | 81 |
82 | 83 | چیزی که در جاوا زیاد داریم در واقع "َAbstract متد های تنها" هستند که در واقع متد هایی هستند که در داخل کلاس اینترفیس ساخته میشن و یک نمونه ساده میتونه اینترفیس Runnable باشه. 84 | 85 | میتونیم به مانند بقیه اینترفیس ها اونو در یک کلاس کاتلین استفاده کنیم، مثلا کد زیر: 86 | 87 |
88 | 89 | 90 | ```kotlin 91 | class RunnableKotlin : Runnable{ 92 | override fun run() { 93 | TODO("not implemented") 94 | } 95 | } 96 | ``` 97 | 98 |
99 | 100 | ولی خب این یک راه حل خیلی ضایع برای این کاره، چرا که درواقع داریم یک کلاس رو که تنها یک تابع داره رو برای این موضوع به کار میبریم. میتونیم به مانند جاوا 1.8 به یک روش دیگه ازش استفاده کنیم: 101 | 102 |
103 | 104 | ```kotlin 105 | val runnable = Runnable { println("Invoking") } 106 | ``` 107 | 108 |
109 | 110 | در واقع اجازه داده شده که تا بلاک کد رو پاس بدیم بدون اینکه در گیر استفاده از یک اینترفیس بشیم 111 | 112 |
113 | -------------------------------------------------------------------------------- /src/talking-to-kotlin-from-java/README.md: -------------------------------------------------------------------------------- 1 |
2 | 3 | # صحبت کردن با کاتلین از جاوا 4 | 5 | حالا میخوایم یکم از کاتلین داخل Java استفاده کنیم.بیاین یک کلاس جاوا با نام TalkingToKotlin بنویسیم: 6 | 7 |
8 | 9 | ```java 10 | public class TalkingToKotlin { 11 | public static void main(String[] args) { 12 | CustomerKotlin customerKotlin = new CustomerKotlin(1,"Sina",null); 13 | } 14 | } 15 | ``` 16 | 17 |
18 | 19 | یادتون میاد که کلاسی داشتیم به نام CustomerKotlin که چند متغییر غیر null داخل خودش داشت. 20 | 21 |
22 | 23 | ```kotlin 24 | data class CustomerKotlin(var id: Int, var name: String, var email: String) 25 | ``` 26 | 27 |
28 | 29 | کاتلین متوجه این موضوع میشه و زمانی که داریم یک متغییر از این کلاس میسازیم اینو در نظر میگیره و بهمون میگه این متغییر نمیتونه مقدار null بگیره! درواقع ما میتونیم مقدار null وارد کنیم ولی خود کامپایلر بهمون اخطار میده که نباید مقدار null وارد بشه 30 | 31 | 32 | 33 | حالا فرض کنین میخوایم به یک متغیر کلاس کاتلین در داخل کلاس جاوا دسترسی داشته باشیمو چیزی که توی جاوا تعریف نشده اینه که دسترسی مستقیم به متغیره! اینجا راه حل خیلی سادس. شما میتونین از متد های set و get استفاده کنین. 34 | 35 |
36 | 37 | ```java 38 | customerKotlin.setEmail("Sina@darvishi.net"); 39 | ``` 40 | 41 |
42 | 43 | ولی خب درمورد متغیر های field چی ؟ اگه یادتون باشه توی کاتلین field نداریم، توی کاتلین تنها خصیصه معنی پیدا میکنه. چه اتفاقی میفته وقتی توی جاوا هستیم ؟ توی جاوا مفهومی به نام field داریم. 44 | 45 | بیاین به کلاس CustomerKotlin مراجعه کنیم و یک خصیصه به اون اضافه کنیم. 46 | 47 |
48 | 49 | ```kotlin 50 | data class CustomerKotlin(var id: Int, var name: String, var email: String){ 51 | var someProperty = "Value" 52 | override fun toString(): String { 53 | return "{\"id\": \"$id\", \"name\": \"$name\"}" 54 | } 55 | } 56 | ``` 57 | 58 |
59 | 60 | حالا بیاین برگردیم و از این خصیصه توی کلاس جاوامون استفاده کنیم 61 | 62 | 63 | 64 | خب همینطور که میبینین متوجه میشیم که ما نمیتونیم به این متیغیر به مانند یک field دسترسی پیدا کنیم ولی اگه بخوایم به مانند یک field به او دسترسی پیدا کنیم باید چه کاری انجام بدیم؟ در واقع اینجا کاتلین برامون Annotation های قرار داده تا بتونیم این اعمال هارو انجام بدیم. 65 | 66 |
67 | 68 | ```kotlin 69 | @JvmField var someProperty = "Value" 70 | ``` 71 | 72 |
73 | 74 | و حالا به راحتی میتونیم به مانند یک field به متغییرمون دسترسی داشته باشیم 75 | 76 |
77 | 78 | ```java 79 | customerKotlin.someProperty = "this is not Property No more"; 80 | ``` 81 | 82 |
83 | 84 | همینطور که میدونین ما توی کاتلین توابعی داریم که میتونن مقادیر پیشفرض برای ورودیهاشون داشته باشن. چجوری توی جاوا با اینگونه توابع رفتار میشه؟ بیاین یه تابع به کلاس CustomerKotlin اضافه کنیم: 85 | 86 |
87 | 88 | ```kotlin 89 | fun changeStatus(status: String = "OK"){ 90 | 91 | } 92 | ``` 93 | 94 |
95 | 96 | و حالا اگه بخوایم ازشون استفاده کنیم به ارور میخوریم 97 | 98 | 99 | 100 | خب به مانند مشکل قبلی کاتلین برامون Annotation هایی گذاشته که بتونیم این مشکل هارو برطرف کنیم.کافیه اینطور بنویسیم: 101 | 102 |
103 | 104 | ```kotlin 105 | @JvmOverloads fun changeStatus(status: String = "OK"){ 106 | 107 | } 108 | ``` 109 | 110 |
111 | 112 | درواقع این Annotation میاد برامون Overload هارو فراهم میکنه. 113 | 114 | 115 | 116 | مطالب این قسمت کامل نشده است. 117 |
118 | 119 | 120 | -------------------------------------------------------------------------------- /src/talking-to-kotlin-from-java/completion-2.PNG: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/KotlinFarsi/OpenSourceTutorials-Introduction/92e9b633b82753deae74fa498e634a58c863e1d0/src/talking-to-kotlin-from-java/completion-2.PNG -------------------------------------------------------------------------------- /src/talking-to-kotlin-from-java/completion-3.PNG: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/KotlinFarsi/OpenSourceTutorials-Introduction/92e9b633b82753deae74fa498e634a58c863e1d0/src/talking-to-kotlin-from-java/completion-3.PNG -------------------------------------------------------------------------------- /src/talking-to-kotlin-from-java/error-1.PNG: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/KotlinFarsi/OpenSourceTutorials-Introduction/92e9b633b82753deae74fa498e634a58c863e1d0/src/talking-to-kotlin-from-java/error-1.PNG -------------------------------------------------------------------------------- /src/talking-to-kotlin-from-java/warning-1.PNG: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/KotlinFarsi/OpenSourceTutorials-Introduction/92e9b633b82753deae74fa498e634a58c863e1d0/src/talking-to-kotlin-from-java/warning-1.PNG -------------------------------------------------------------------------------- /src/talking-to-kotlin-from-java/warning-2.PNG: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/KotlinFarsi/OpenSourceTutorials-Introduction/92e9b633b82753deae74fa498e634a58c863e1d0/src/talking-to-kotlin-from-java/warning-2.PNG -------------------------------------------------------------------------------- /src/the-kotlin-repl/README.md: -------------------------------------------------------------------------------- 1 |
2 | 3 | # کاتلین REPL 4 | 5 | زمانی که کاتلین رو نصب میکنیم همونطور که دیدید دستور زیر رو در Command Line زدیم. 6 | 7 | 8 | 9 | 10 | محیطی رو برامون بالا میاره که بهش Kotlin REPL میگیم و مخفف Kotlin, Read Eval Print Loop هه که میتونیم بگیم یک محیط ساده تعاملی با کامپایلره و میشه با اون یک سری چیز هارو امتحان کنیم.همینطور که شما می بینین من یک سری کد اینجا مینویسم واین محیط از کامپایلر میخواد که این دستورات رو انجام بده و نتیجش رو پرینت کنه. 11 | 12 | مثلا: 13 | 14 | 15 | 16 | ما حتی می تونیم تابع بنویسیم.بعدا در مورد جزئیات صحبت میکنیم ولی فعلا به عنوان مثال این تابع رو نگاه کنید: 17 | 18 | 19 | 20 | ما میتونیم حتی کدمون رو توی چند خط بنویسیم: 21 | 22 | 23 | 24 | خب، تا اینجا متوجه شدیم که اینREPL رو میتونیم با استفاده از دستور kotlinc در محیط کنسول اجرا کنیم و کنسول هم این محیط تعاملی رو بالا میاره. همینطور میتونیم این محیط رو از یک روش دیگه بالا بیاریم که مقداری فیدبک بیشتری از کدی که زدیم میگیریم و اون هم استفاده از REPL داخل IntelliJ IDEA است که مقداری تجربه کاربری رو افزایش میده. خب پس میریم IntelliJ رو بالا میاریم و یک پروژه جدید شروع میکنیم. و اگر بریم به سمت Tools>Kotlin>kotlin REPL متوجه میشیم که دقیقا همون محیط رو در اینجا داریم. 25 | 26 | 27 | 28 | ولی یکی از خوبی های این محیط اینه که در اینجا همگردانی و اطلاعت پارامتر ها و ... رو داریم، بدین صورت که میتونیم از کمکی که IntelliJ میکنه بهمون استفاده کنیم. حال اگر دوباره دستورات گذشته را وارد کنیم متوجه خواهیم شد که: 29 | 30 |
31 | 32 | #### >>> fun hello(name: String){ print(name) } 33 | #### >>> hello(“Kotlin REPL”) 34 | #### Kotlin REPL 35 | -------------------------------------------------------------------------------- /src/the-kotlin-repl/bye-repl.png: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/KotlinFarsi/OpenSourceTutorials-Introduction/92e9b633b82753deae74fa498e634a58c863e1d0/src/the-kotlin-repl/bye-repl.png -------------------------------------------------------------------------------- /src/the-kotlin-repl/hello-fun.png: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/KotlinFarsi/OpenSourceTutorials-Introduction/92e9b633b82753deae74fa498e634a58c863e1d0/src/the-kotlin-repl/hello-fun.png -------------------------------------------------------------------------------- /src/the-kotlin-repl/hello-world.png: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/KotlinFarsi/OpenSourceTutorials-Introduction/92e9b633b82753deae74fa498e634a58c863e1d0/src/the-kotlin-repl/hello-world.png -------------------------------------------------------------------------------- /src/the-kotlin-repl/kotlinc-command.png: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/KotlinFarsi/OpenSourceTutorials-Introduction/92e9b633b82753deae74fa498e634a58c863e1d0/src/the-kotlin-repl/kotlinc-command.png -------------------------------------------------------------------------------- /src/the-kotlin-repl/repl-in-idea.png: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/KotlinFarsi/OpenSourceTutorials-Introduction/92e9b633b82753deae74fa498e634a58c863e1d0/src/the-kotlin-repl/repl-in-idea.png -------------------------------------------------------------------------------- /src/the-structure-of-kotlin-application/README.md: -------------------------------------------------------------------------------- 1 |
2 | 3 | # ساختار یک برنامه کاتلین 4 | 5 | خب حالا بیاین در مورد ساختار یک برنامه Kotlin صحبت کنیم. یک فایل کاتلین به نام main.kt میسازیم و داخلش خط های زیر را مینویسیم : 6 | 7 |
8 | 9 | ```kotlin 10 | fun main(args: Array) { 11 | println("Hello World!") 12 | } 13 | ``` 14 |
15 | 16 | خب در اینجا به یک نکته باید توجه کنیم. این که کاتلین نیازی به نقطه ویرگول";" نداره و اضافه کردن نقطه ویرگول کاملا دلخواه است. تنها در یک جا هست که در شرایط ویژه باید از نقطه ویرگول استفاده کنیم که بعدا در مورد اون صحبت خواهیم کرد ولی در موارد غیر اون استفاده از نقطه ویرگول کاملا دلخواه است. 17 | 18 | اگر متوجه شده باشید کلیدواژه fun نشان دهنده اینه که ما چطور در زبان کاتلین یک تابع رو میسازیم و اگر دقت کنید من یک تابع رو داخل یک فایل نوشتم و نیاز به ساختن هیچ کلاسی نداشتم و این هم به این دلیل است که ما در کاتلین چیزی به نام Top-Level Functions داریم. دقیقا به مانند جاوااسکریپت، میتونیم یک فایل رو باز کنیم و یک تابع رو داخلش بنویسیم، بدون نیاز به نوشتن کلاسش. 19 | 20 | چرا من اسم این تابع رو main گذاشتم؟ باید بدونیم که main یک نقطه شروع برای کامپایلر به حساب میاد. درواقع مشخص کردم که این یک تابع ورودی برنامه است. 21 | 22 | خب تا اینجا من این فایل رو ذخیره میکنم. و سپس دستور زیر رو توی کنسول میزنم: 23 | 24 |
25 | 26 | #### >>kotlinc Main.kt 27 | 28 |
29 | 30 | و این درواقع یک سری فایل رو برای من خروجی میده. یک فولدر به نام META-INF که اینجا مورد نظرمون نیست، و یک MainKt.class که در واقع همان بایت کد های جاوایی هست که کاتلین برامون ساخته. 31 | 32 | خب برگردیم سراغ فایل Main، اگر دقت کنین میبینین که هیچگونه اطلاعاتی در مورد package هم نیست! ما در کاتلین مفهوم پکیج رو داریم ولی اگر پکیج مشخص نشه، کاتلین اون رو به صورت پکیج دیفالت در نظر میگیره ولی من میتونیم بیام و به اون صورت کدم رو تغییر بدم: 33 | 34 |
35 | 36 | ```kotlin 37 | package com.kotlinfarsi.introduction 38 | 39 | fun main(args: Array) { 40 | println("Hello World!") 41 | } 42 | ``` 43 | 44 |
45 | 46 | حالا اگر دوباره فایلمون رو کامپایل کنیم،با همون دستور قبلی: 47 | 48 |
49 | 50 | #### >>kotlinc Main.kt 51 | 52 |
53 | 54 | و حالا اگه خروجی رو نگاه کنیم متوجه میشیم که فولدری به نام com ساخته شده است و اگر به داخلش بریم متوجه میشیم که داخلش یک فولدر دیگه ای هست به نام kotlinfarsi و اگر به داخل ان رفته فولدر دیگری به نام introduction خواهیم دید و اگر به داخل ان نیز رفته متوجه خواهیم شد که فایلی به نام MainKt.class در اونجا ساخته شده است. درواقع کاتلین اجباری به مسئله Packaging نمیکنه ولی در واقع برای مرتب بودن کدمون پیشنهاد میشه که همچین کاری صورت بگیره و در واقع همونطور که قبلا گفتیم کاتلین jvm رو هدف خودش قرار داده و این مسئله Packaging کاریه که خیلی از توسعه دهنده های جاوا انجام میدم واین درواقع کار خوبیه. 55 | 56 | خب حالا بیاین برناممون رو اجرا کنیم، به سه فولدر قبل برمیگردیم، همونجایی که فولدر com در اون قرار داشت و همینطور فایل Main.kt و فایل کامپایل اولمون MainKt.class . 57 | 58 | خب اگر دستور زیر رو وارد کنیم : 59 | 60 |
61 | 62 | #### >>java com.kotlinfarsi.introduction.MainKt 63 | 64 |
65 | 66 | با ارور مواجه میشیم!! دلیل این ارور هم اینه که کاتلین به همراه یک runtime ارائه شده!! درواقع شما برای اجرای برنامه های کاتلین باید این رانتایم رو همراه برنامتون کنین. میتونیم این رانتایم رو به کامپایلر include کنیم، درواقع همراه کامپایلرمون جاساز کنیم و دلیل این که برنامه ناموفق بود اینه که نتونست رانتایم رو پیدا کنه. من نمیدونم شما رانتایمتون رو کجا ذخیره کردین. اگر فایل زیپ شده رو دانلود کردین داخل فولدر lib و یا اگر با brew نصبش کردین با دستور which پیداش کنین، به هر حال اگه به محل رانتایمتون برین متوجه خواهید شد که فایلی به نام kotlin-runtime.jar داریم که همون رانتایم مورد نظرمونه. 67 | 68 | خب به هر حال ما میخوایم فایلمون رو اجرا کنیم و یک روش اینه که شما از همون اول مشخص کنین که فایل رانتایمتون کجا قرار داره، مثلا کد زیر رو بزنین: 69 | 70 |
71 | 72 | #### >>java –cp <ادرس فایل رانتایم> com.kotlinfarsi.introduction.MainKt 73 | #### Hello World 74 | 75 |
76 | 77 | بعله، فایلمون اجرا شد، خروجی رو نمایش دادیم! 78 | 79 | ولی خب اگه چنتا فایل کاتلین داشتیم چی ؟ باید فایل class همه ی اون ها رو به کاربر بفرستیم و بگیم اجراش کن؟ خب درواقع همونطور که جاوا برای این منظور فایل .jar درست میکرد، کاتلین هم همین کار رو میکنه. تنها کاری که باید بکنیم اینه که دستور زیر رو وارد کنیم: 80 | 81 |
82 | 83 | #### >>kotlinc Main.kt –d hello.jar 84 | 85 |
86 | 87 | و اگر نگاه کنیم فایلی به نام hello.jar در کنار فایلامون خواهیم داشت. خب اگر من بخوام اجراش کنم بازم با همون ارور مواجه میشم چراکه نمیتونه فایل رانتایم رو پیدا کنه. کامپایلر کاتلین درواقع به ما این امکان رو میده که بتونیم رانتایم رو include کنیم : 88 | 89 |
90 | 91 | #### >>kotlinc Main.kt –include-runtime –d hello.jar 92 | 93 |
94 | 95 | و حالا تنها کاری که من باید انجام بدم اینه که دستور زیر رو وارد کنم: 96 | 97 |
98 | 99 | #### >>java –jar hello.jar 100 | #### Hello World! 101 | 102 | 103 | -------------------------------------------------------------------------------- /src/top-level-functions-and-properties-in-kotlin/README.md: -------------------------------------------------------------------------------- 1 |
2 | 3 | # توابع و خصیصه های درجه اول 4 | 5 | خب همینطور که میدونین ما توی کاتلین توابع Top-Level داشتیم و چیزی که توی جاوا تعریف نشده این گونه توابعه. چجوری میتونیم از اینگونه توابع استفاده کنیم ؟ 6 | 7 | یک کلاس به نام TopLevelFunctions میسازیم 8 | 9 |
10 | 11 | ```kotlin 12 | fun prefix(prefix: String, value : String): String = "$prefix-$value" 13 | ``` 14 | 15 |
16 | 17 | و این تابع رو داخلش مینویسیم. در واقع کامپایلر وقتی این فایل رو کامپایل میکنه یک فایلی به نام TopLevelFunctionsKt.class میسازه 18 | 19 | 20 | 21 | یعنی درواقع کلاس TopLevelFunctions از فایل ToplevelFunctions جدا میشه! ما اگه کلاسی به همین نام در این فایل ایجاد کنیم و کامپایلش کنیم متوجه میشیم که فایل .class مربوط به اون کلاس رو جدا از فایل اصلی ساخته! 22 | 23 | 24 | 25 | و داخل کد هم همین قضیه برقراره، اگه بخوایم به فایل دسترسی پیدا کنیم باید از TopLevelFunctionKt استفاده کنیم و اگر به کلاس از TopLevelFunction. 26 | 27 |
28 | 29 | ```java 30 | TopLevelFunctionsKt.prefix("Hi","Sina"); 31 | ``` 32 | 33 |
34 | 35 | به همین راحتی. این قضیه برای خصیصه های Top-Level نیز برقراره ولی با این تفاوت که از getter و setter ها استفاده میکنیم.ولی البته که اگر بخواین میتونین به صورت field دسترسی داشته باشین و راهش استفاده از const هه . به راحتی کد زیر 36 | 37 |
38 | 39 | ```kotlin 40 | const val year = 2017 41 | ``` 42 | 43 |
44 | 45 | البته یادتون باشه که نمیتونین برای متغییر های var از const استفاده کنین! 46 | 47 |
48 | -------------------------------------------------------------------------------- /src/top-level-functions-and-properties-in-kotlin/output-1.png: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/KotlinFarsi/OpenSourceTutorials-Introduction/92e9b633b82753deae74fa498e634a58c863e1d0/src/top-level-functions-and-properties-in-kotlin/output-1.png -------------------------------------------------------------------------------- /src/top-level-functions-and-properties-in-kotlin/output-2.png: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/KotlinFarsi/OpenSourceTutorials-Introduction/92e9b633b82753deae74fa498e634a58c863e1d0/src/top-level-functions-and-properties-in-kotlin/output-2.png -------------------------------------------------------------------------------- /src/tuples/README.md: -------------------------------------------------------------------------------- 1 |
2 | 3 | # چندتایی ها (Tuples) 4 | 5 | چندگانه ها زمانی استفاده میشن که شما به عنوان مثال خروجی یک تابع رو بخواین به صورت یک مجموعه دوگانه یا سه گانه برگردونید. باید در نظر داشته باشین که اگر تعداد خروجی هاتون بیشتر از 3 تا هست باید از کلاس ها استفاده کنید و چندگانه ها در کاتلین تا سه گانه ها بیشتر پشتیبانی نمی شوند. 6 | 7 | خب اول بیاین یک تابع درست کنیم که یک دوگانه از جمله هارو برگردونه. مثلا یک تابع داشته باشیم که قراره اسم کشور رو بگیره و اسم پایتخت و جمعیت رو برگردونه. 8 | 9 |
10 | 11 | ```kotlin 12 | fun capitalAndPopulation(country: String): Pair{ 13 | return Pair("Madrid",2000000) 14 | } 15 | 16 | fun main(args: Array) { 17 | val result = capitalAndPopulation("Spain") 18 | println(result.first) 19 | println(result.second) 20 | } 21 | ``` 22 | 23 |
24 | 25 | خروجی تابعمون به صورت Pair هستش و وقتی میخوایم از تابع استفاده کنیم کافیه بگیم متغیر اول رو میخوایم یا دوم. 26 | 27 | حالا اگه بخوایم یک سه گانه رو برگدونیم به این روش انجامش میدیم. 28 | 29 |
30 | 31 | ```kotlin 32 | fun countryInformation(country: String): Triple{ 33 | return Triple("Madrid", "Europe",2300000) 34 | } 35 | 36 | fun main(args: Array) { 37 | val countryInfo = countryInformation("Spain") 38 | println(countryInfo.first) 39 | println(countryInfo.second) 40 | println(countryInfo.third) 41 | } 42 | ``` 43 | -------------------------------------------------------------------------------- /src/type-casting-in-kotlin/README.md: -------------------------------------------------------------------------------- 1 |
2 | 3 | # type casting در کاتلین 4 | 5 | پیشنهاد میشه این قسمت رو بر روی IntellJ IDEA امتحان کنید 6 | 7 | خب به قسمتی رسیدیم که دقیقا به بخش خاصی تعلق ندارن ولی خب نکات مهمی رو پوشش میده. 8 | 9 | ممکنه شما متوجه یک چیز توی Null Checks ها شده باشین و من با همون شروع میکنم. 10 | 11 | تا اینجا یادتون میاد که این کد رو داشتیم 12 | 13 |
14 | 15 | ```kotlin 16 | fun main(args: Array) { 17 | var nullMessage :String? = null 18 | println(nullMessage.length) 19 | } 20 | ``` 21 | 22 |
23 | 24 | و خب گفتیم اگه متغیری بتونه مقدار null رو بگیره، باید قبل استفاده ازش چک بشه، و چک کردنش رو هم با "?" انجام میدادیم. خب حالا اگه بیاین قبل استفاده از nullMessage یک مقدار بهش بدین 25 | 26 |
27 | 28 | ```kotlin 29 | fun main(args: Array) { 30 | var nullMessage :String? = null 31 | nullMessage = "Some Value" 32 | println(nullMessage?.length) 33 | } 34 | ``` 35 | 36 |
37 | 38 | کامپایلر یه اخطار کوچولو بهمون میده و میگه : "نیازی نیست متغیر غیر null رو چک کنیم".یعنی میتونیم "?" رو برداریم. 39 | 40 |
41 | 42 | ```kotlin 43 | fun main(args: Array) { 44 | var nullMessage :String? = null 45 | nullMessage = "Some Value" 46 | println(nullMessage.length) 47 | } 48 | ``` 49 | 50 |
51 | 52 | ولی خب تا اون رو برمیداریم اون متغیر یک بک گراند سبز میگیره به خودش و اگه بریم و موس رو روش نگه داریم متوجه میشیم که نوشته "Smart cast to kotlin.String". این به چه معنیه؟ بهتون نشون میدم. 53 | 54 | بیاین یک فایل به نام Casting درست کنیم و کد زیر رو توش بزنیم 55 | 56 |
57 | 58 | ```kotlin 59 | open class Person 60 | 61 | class Employee: Person(){ 62 | fun vactionDays(days: Int){ 63 | if(days < 60) 64 | println("You need more vacation") 65 | } 66 | } 67 | 68 | class Contractor: Person() 69 | 70 | fun hasVacations(obj: Person){ 71 | if(obj is Employee){ 72 | 73 | } 74 | } 75 | fun main(args: Array) { 76 | 77 | } 78 | ``` 79 | 80 |
81 | 82 | خب تا اینجا کار خاصی نکردیم.دوتا کلاس ساختیم به نام های Employee و Contactor که از کلاس Person ارث بری میشن و همچنین داخل Employee یک متد ساختیم. خب حالا بعدش اومدیم و یک تابع داخل فایلمون ساختیم به نام hasVacations که توش یک شرط داره که البته بدنه شرط رو هنوز ننوشتیم، ولی خب میدونیم که اگر obj یک شی از نوع Employee بود داخل if میره. خب اگه بریم داخل if و بخوایم بنویسم obj.vacationDays متوجه میشیم که IntelliJ برامون ادامه اش رو مینویسه! توجه کنین که obj از نوع کلاس Person بود که تابعی به اون اسم نداره! اگه کد رو کامل بنویسیم متوجه میشیم که دوباره همون حالت پیش میاد، دوباره مینویسه "Smart casting to Employee" . 83 | 84 |
85 | 86 | ```kotlin 87 | open class Person 88 | 89 | class Employee: Person(){ 90 | fun vactionDays(days: Int){ 91 | if(days < 60) 92 | println("You need more vacation") 93 | } 94 | } 95 | 96 | class Contractor: Person() 97 | 98 | fun hasVacations(obj: Person){ 99 | if(obj is Employee){ 100 | obj.vactionDays(20) 101 | } 102 | } 103 | 104 | fun main(args: Array) { 105 | 106 | } 107 | ``` 108 | 109 |
110 | 111 | یعنی کامپایلر میاد میگه " من متوجه میشم که زمانی این کد اجرا میشه که obj یک Employee باشه و نیازی نیست که مثل جاوا اینجوری (Employee)obj.vacationDays(20) بنویسیمش 112 | 113 | درواقع خود کامپایلر برامون انجامش میده و به اندازه کافی هوشمند هست که بتونه این کار رو انجام بده. 114 | 115 | حالا اگه برگردیم به قسمت Nulls و کدمون رو نگاه کنیم 116 | 117 |
118 | 119 | ```kotlin 120 | fun main(args: Array) { 121 | var nullMessage :String? = null 122 | nullMessage = "Some Value" 123 | println(nullMessage.length) 124 | } 125 | ``` 126 | 127 |
128 | 129 | درواقع کامپایلر اینجا میگه "من میدونم این متغیر رو جوری تعریف کردی که میتونه null باشه، ولی خب قبل چک کردنش بهش مقدار دادی، پس من خودم به یک رشته(غیر قابل null شدن) تبدیلش میکنم که نیازی نداشته باشه که چک بشه!" 130 | 131 | خب حالا فهمیدیم که کامپایلر هوشمنده و بعضی جاها خودش cast رو انجام میده، ولی اگه بعضی جاها ما خودمون بخوایم این casting رو انجام بدیم چیکار باید بکنیم؟ 132 | 133 | درواقع با کلیدواژه "as" این کار رو انجام میدیم. 134 | 135 |
136 | 137 | ```kotlin 138 | var input : Any = 10 139 | fun main(args: Array) { 140 | val str = input as String 141 | println(str.length) 142 | } 143 | ``` 144 | 145 |
146 | 147 | اینجا گفتیم که میدونیم input از جنس Any هستش، ولی اینجا میخوایم به String کستش کنیم و طولش رو برام بگیریم. تنها کاری که کردیم اون وسط این بود که از کلیدواژه as استفاده کردیم. 148 | 149 | البته خب قبل اجرا هیچ مشکلی نداشتیم و هیچ اروری هم نبود. ولی خب وقتی کد رو اجرا میکنیم به ارور میخوریم 150 | 151 | 152 | 153 | و اونم به این دلیله که اگه یادتون باشه گفتیم هیچ گونه کستینگ به صورت لفظی در کاتلین نداریم و اگه بخوایم یک متغیر رو کست کنیم باید از توابعش استفاده کنیم. 154 | 155 | خب حالا ما چطوری میتونیم این کارو به یک روش امن انجام بدم؟ 156 | 157 | کاری که اینجا انجام میدیم اینجوریه 158 | 159 |
160 | 161 | ```kotlin 162 | var input : Any = 10 163 | fun main(args: Array) { 164 | val str = input as? String 165 | println(str?.length) 166 | } 167 | ``` 168 | 169 |
170 | 171 | به این معنی که من این دفعه "تلاش" میکنم که input رو به String تبدیل کنم. 172 | 173 |
174 | -------------------------------------------------------------------------------- /src/type-casting-in-kotlin/result-1.PNG: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/KotlinFarsi/OpenSourceTutorials-Introduction/92e9b633b82753deae74fa498e634a58c863e1d0/src/type-casting-in-kotlin/result-1.PNG -------------------------------------------------------------------------------- /src/typealias-in-kotlin/README.md: -------------------------------------------------------------------------------- 1 |
2 | 3 | # typealias در کاتلین 4 | 5 | 6 | خب به قسمتی رسیدیم که دقیقا به بخش خاصی تعلق ندارن ولی یکی از ابزاری که میتونه خیلی کمکمون کنه. 7 | typealias ها به ما این امکان رو میدن که بتونیم یک اسم جایگزین برای کلاس هایی که میخوایم استفاده کنیم بزاریم. 8 | 9 | 10 | مثلا میتونیم اسم یکی از کلاس هامون رو کوتاه کنیم و از این به بعد از اون اسم جایگزین استفاده کنیم 11 | مثلا فرض کنید که کلاسی به این اسم داریم: 12 |
13 | 14 | 15 | 16 | ```kotlin 17 | MutableMap> 18 | ``` 19 | 20 | 21 |
22 | 23 | و خیلی قراره از این کلاس جاهای مختلفی استفاده کنیم که یقینا برای اینکه هربار این کلاس رو فراخونی کنیم و ازش نمونه بسازیم یه مقدار کلافه کننده ست، 24 | خوب اینجاست که این ابزار در کاتلین به کمکمون میاد و به ما این امکان رو میده که یک اسم جایگزین برای همچین کلاسی بنویسیم و از این به بعد از این نام کوتاه جای این نام طولانی کلاس استفاده کنیم. 25 |
26 | 27 | ```kotlin 28 | typealias FileTable = MutableMap> 29 | ``` 30 | 31 |
32 | حتی میشه از اونا برای اسم جایگزین توی inner class ها استفاده کرد: 33 |
34 | 35 | 36 | ```kotlin 37 | class Food { 38 | inner class Pizza{ 39 | //Codes... 40 | } 41 | } 42 | 43 | typealias PizzaInnerFood = Food.Pizza 44 | ``` 45 | 46 |
47 | نکته ای که باید بهش دقت کنید اینه که typealias ها یک کلاس یا تایپ جدیدی رو ارائه نمیدن بلکه فقط یه اسم جایگزین رو برای یک کلاس ارائه میدن. 48 |
49 | 50 | 51 | ```kotlin 52 | typealias ArrName = ArrayList; 53 | 54 | MainActivity : AppCompatActivity(){ 55 | override fun onCreate(savedInstanceState: Bundle?) { 56 | super.onCreate(savedInstanceState) 57 | val names = ArrName() 58 | names.add("Ali") 59 | names.add("Kamran") 60 | names.add("Sara") 61 | } 62 | } 63 | ``` 64 | -------------------------------------------------------------------------------- /src/visibility-modifiers-in-kotlin/README.md: -------------------------------------------------------------------------------- 1 |
2 | 3 | # visibility modifier ها در کاتلین 4 | اگه دقت کرده باشین در تموم کد هایی که تا الان نوشیتم از هیچ گونه visibility-modifier ای استفاده نکردیم. و در واقع در کاتلین این قرارداد هست که visibility-modifier پیش فرض public است. 5 | 6 | توی کاتلین 4 نوع visibility-modifier داریم: 7 | - Public که پیشفرضمونه و از همه جا قابل دسترسیه 8 | برای Top-Level-Declaration ها ( منظور تموم تعریف هایی که به صورت Top-level انجام میشه، مثلا Top-level-function ها ) 9 | - Private که تنها از داخل همون فایلی که تعریف شده قابل دسترسیه 10 | - Internal که در واقع این اجازه رو میده که از هرجای برنامه بتونیم به اون دسترسی داشته باشیم، تازمانی که داخل همون module که توش تعریف شده باشیم. درواقع module اینجا منظورمون gradle module ، maven module و غیره و امثال این هاست 11 | برای کلاس ها ما 3 نوع Visibility-modifier داریم 12 | - Private تنها دسترسی رو به عضو های یک class میده 13 | - Protected به مانند private میمونه ولی علاوه بر اون دسترسی رو به subclass ها هم میده 14 | - Internal در واقع اجازه میده که هر چیزی داخل module به اون دسترسی داشته باشه. 15 | -------------------------------------------------------------------------------- /src/welcome-to-the-course/README.md: -------------------------------------------------------------------------------- 1 |
2 | 3 | # به دوره خوش آمدید 4 | 5 | امروز میخوایم در مورد کاتلین ( Kotlin ) صحبت کنیم که یک زبون برنامه نویسی است که در شرکت JetBrains توسعه داده شده. 6 | این دوره بیشتر شما که توسعه دهنده نرم افزار یا معماری است که ممکنه با JVM اشنا نباشید، ما بعضی قسمت هارو که نیاز به JVM داره رو پوشش میدیم پس نیاز به نگرانی نداره اگر چیزی قبلش ندیده باشین از این ها و همچنین ما کمی درمورد پایه Kotlin صحبت خواهیم کرد و همچنین این دوره به شما اطلاعات زیادی میده تا شما بتونین این زبون برنامه نویسی رو شروع کنین و البته در قسمت پیشرفته ( Advance ) یک سری اطلاعات بیشتری در مورد این زبون برنامه نویسی خواهید دید.خب پس شروع کنیم. 7 | 8 | -------------------------------------------------------------------------------- /src/why-kotlin/README.md: -------------------------------------------------------------------------------- 1 |
2 | 3 | # چرا کاتلین 4 | 5 | 6 | قبل از شروع باید یک توضیح ارائه کنیم که چرا باید سراغ این زبون بریم؟ 7 | ابتدا باید بگیم که پروژه کاتلین در سال 2010 توسط شرکت JetBrains شروع شد. در اون زمان نیاز به یک زبون احساس میشد که هم مختصر و هم پرمعنا باشه و هم ابزار های زیادی براش موجود باشه وهمچنین بتونه با زبون های دیگه هم ارتباط برقرار کنه و همکاری داشته باشه. 8 | خب همینطور که میدونید جاوا یک زبونیه که هم طرفدار زیادی داره و هم خب خیلی فوق العادس ولی مشکلاتی داره اینه که کد ها مختصر نیستن و البته خیلی از ویژگی های زبان های برنامه نویسی مدرن رو شامل نشده چرا که ما به دنبال یک زبون برنامه نویسی مدرنی هستیم که بتونه مشکلات برنامه نویسی توسعه دهنده ها رو که هرروزه باهاش دست و پنجه نرم میکنن رو رفع کنه. پس شروع به توسعه کاتلین کردیم. همچنین کاتلین لایسنس Apache 2 رو داره. 9 | کاتلین یک statically typed language هست ( کلمه بهتری جایگزینش پیدا نکردم ) 10 | کاتلین از زبون های به مانند Java,Scala,C#,groovy الهام گرفته شده. 11 | کاتلین دو قسمت رو هدف قرار داده.یکی JVM و دیگری JS . کدی کاتلینی که شما میزنین مستقیم توسط JVM قابل استفاده است و همچنین کدتون قابلیت تبدیل به JavaScript رو هم داره بدین معنی که شما میتونین هم قسمت سمت سرور و هم قسمت سمت مرورگر رو با کاتلین بنویسین.یکی از هدف های این زبون اینه که بتونیم توی سیستم عامل های مختلف اجراش کنیم والبته این شرکت بخش دیگه ای رو هم دارن روش کار میکنن به نام Kotlin/Native (خیلیا دوست دارن بهش بگن KotN ) که به ما این قابلیت رو میده که کد کاتلینمون بتونه به طور Native برروی پلتفورم های مختلف کار کنه.به عنوان مثال iOS و یا macOS و حتی IoT و Embedded Systemها . 12 | همینطور که گفتیم این زبون قابلیت این رو داره که بتونه با جاوا همکاری کنه، این بدین معنیه که شما کدتون هم داخل کد جاوا قابل استفاده است و هم کد جاواتون داخل فایل کاتلین. این به این معنیه که تموم لایبری هایی که برای زبون Java نوشته شده بتونه توی این زبون هم قابل استفاده قرار بگیره. این زبون از Build سیستم هایی مثل Gradle و Maven هم استفاده میکنه. 13 | همینطور که شاید خبر داشته باشین کاتلین رسما توسط شرکت گوگل برای برنامه نویسی اندروید قابل استفاده است و این خیلی خبر خوبی برای توسعه دهنده هاست چراکه میتونن با خیلی از ویژگی های Java 1.8 که نمیتونستن قبلا در اندروید استفاده کنند کار کنن. 14 | چون این زبون از زبون های دیگه ای به مانند Java و C# و ... الهام گرفته شده، خیلی هم به مثل همون زبون هاست که به این معنیه که زمان یادگیری سینتکس رو کاهش میده و شما در طی چند روز متوجه میشین که زبون به شدت ساده ای هستش 15 | یکی از خوبیای این زبون اینه که نیازی نداریم که این همه کدی که دهه هاست در زبون جاوا زده شده رو دور بندازیم. البته که JNI هم در این زبون پشتیبانی میشه و پس ما میتونیم از توابع C و C++ استفاده کنیم. 16 | -------------------------------------------------------------------------------- /src/working-with-abstract-classes-in-kotlin/README.md: -------------------------------------------------------------------------------- 1 |
2 | 3 | # کارکردن با کلاس های abstract در کاتلین 4 | 5 | اگر با مفهوم abstract اشنا باشید کلاسی مد نظرمون هست که نمیتونیم ازش نمونه ای رو بسازیم ولی میتونیم از اون ارثبری کنیم. 6 | 7 |
8 | 9 | ```kotlin 10 | abstract class StoredEntity 11 | 12 | class Employee: StoredEntity() 13 | 14 | fun main(args: Array) { 15 | val se = Employee() 16 | } 17 | ``` 18 | 19 |
20 | 21 | خب حالا با خودتون میگین چه فایده ای داره که از کلاس های abstract استفاده کنیم؟ خب در واقع کلاس های abstract تفاوتی با کلاس های پایه ای دارند و اونم اینه که یک کلاس abstract میتونه هم مانند یک کلاس معمولی یک تابع/متغییر که مقدار دهی شده داشته باشه، و هم یک تابع abstract داشته باشه ک پیاده سازی نشده. مثلا فرض کنید که چندین کلاس داریم که یک سری کار انجام میدن ولی محتوای کارشون شبیه به هم با اندکی تفاوته، برای همین میایم یک کلاس abstract میسازیم و تابع abstract اون رو هم میسازیم ولی بدنه تابع رو توی هر کدوم از کلاس ها بسته به نوع کلاسمون میسازیم.مثال زیر رو نگاه کنین: 22 | 23 |
24 | 25 | ```kotlin 26 | abstract class StoredEntity{ 27 | abstract fun store() 28 | } 29 | 30 | class Employee: StoredEntity() { 31 | 32 | override fun store() { 33 | TODO("not implemented") 34 | } 35 | } 36 | ``` 37 | 38 |
39 | 40 | البته تموم عضو های کلاس abstract نیازی به abstract بودن خودشون ندارن: 41 | 42 |
43 | 44 | ```kotlin 45 | abstract class StoredEntity{ 46 | val isActive = true 47 | 48 | abstract fun store() 49 | 50 | fun status():String{ 51 | return isActive.toString() 52 | } 53 | } 54 | 55 | class Employee: StoredEntity() { 56 | override fun store() { 57 | TODO("not implemented") 58 | } 59 | } 60 | 61 | fun main(args: Array) { 62 | val se = Employee() 63 | 64 | se.isActive 65 | se.status() 66 | } 67 | ``` 68 | 69 |
70 | 71 | فقط همینطور که میدونید ما نمیتونیم توی main دوباره به isActive مقدار بدیم. 72 | 73 |
74 | 75 | 76 | -------------------------------------------------------------------------------- /src/working-with-basic-types-in-kotlin/README.md: -------------------------------------------------------------------------------- 1 |
2 | 3 | # کار با Type های پایه ای 4 | 5 | در کاتلین در واقع همه چیز یک شی (object) است. خب به عنوان مثال اگر به یک Integer نگاه کنیم، مثلا کد زیر: 6 | 7 |
8 | 9 | ```kotlin 10 | var myInt : Int 11 | ``` 12 | 13 |
14 | 15 | در واقع Int یک شی است. درواقع ما تایپ های متفاوتی برای یک مقدار های عددی داریم، Byte ، Long ، Float ، Double . همینطور که میبینید ما یک سری تایپ داخلی برای متغیر ها داریم. 16 | 17 | حالا اگه یادتون باشه گفتیم نیاز نیست توی کاتلین تایپ ها رو وقتی مقدار دهی کردیم بنویسیم 18 | 19 |
20 | 21 | ```kotlin 22 | var myLong = 10 23 | ``` 24 | 25 |
26 | 27 | یعنی مثلا توی بالا کاتلین باید متوجه بشه که منظورمون چیه، ولی این اتفاق نمیفته و اگر myLong رو نگاه کنیم متوجه خواهیم شد که این مقدار یک Int است! خب البته کاتلین راهی برای این قضیه داره، کافیه که ما عبارت بالا رو به صورت مقابل بنویسیم 28 | 29 |
30 | 31 | ```kotlin 32 | var myLong = 10L 33 | ``` 34 | 35 |
36 | 37 | و حالا کاتلین متوجه میشه که شما Long میخواین. 38 | 39 | حالا اگه شما میخواین تایپ های دیگه رو معرفی کنید میتونید به این صورت بنویسین. 40 | 41 |
42 | 43 | ```kotlin 44 | val myLong = 10L 45 | val myFloat = 100F 46 | val myHex = 0x0F 47 | val myBinary = 0xb01 48 | ``` 49 | 50 |
51 | 52 | توی کاتلین همونطور که گفتم نمیتونین همینجوری یک تایپ رو توی یک تایپ دیگه بریزین 53 | 54 |
55 | 56 | ```kotlin 57 | val myInt = 10 58 | val myLongAgain: Long = myInt 59 | ``` 60 | 61 |
62 | 63 | شما نمیتونید اینجوری که بالا نوشتم بنویسین ولی راهی هست که بتونین مقدار یک Int رو توی Long بریزین. باید از توابع اون تایپ استفاده کنید یعنی خط بالا رو به این صورت بنویسین 64 | 65 |
66 | 67 | ```kotlin 68 | val myInt = 10 69 | val myLongAgain: Long = myInt.toLong() 70 | ``` 71 |
72 | 73 | که درواقع اجازه میده یک مقدار رو تبدیل کنید به یک مقدار دیگه. 74 | 75 | حالا بیاین بریم سراغ رشته ها،قطعه کد زیر رو ببینیم 76 | 77 |
78 | 79 | ```kotlin 80 | val myChar = 'A' 81 | val myString = "My String" 82 | ``` 83 | 84 |
85 | 86 | خب اگه دقت کنید کامپایلر با استفاده از " ‘ " متوجه میشه که این ایا کاراکتره یا ایا یک رشته است. 87 | 88 |
89 | 90 | ```kotlin 91 | val escapeCharacters = "A new Line \n" 92 | ``` 93 | 94 |
95 | 96 | میتونید از کاراکتر های پایان دهنده استفاده کنید. 97 | 98 |
99 | 100 | ```kotlin 101 | val rawString = "Hello " + 102 | "This is second line" + 103 | "a third line" 104 | 105 | val multipleLine = """ 106 | this is a string 107 | and this is another line 108 | """ 109 | ``` 110 | 111 |
112 | 113 | میتونید یک رشته رو در چند خط بنویسین.یک روش اینه که با استفاده از + در چند خط یک رشته رو بنویسید و یا این که با استفاده از 3 تا " " " بگین میخوایم یک رشته چند خطی بنویسیم. میتونید یک مقدار رو داخل یک رشته استفاده کنید.البته به دو روش که روش دوم خلاصه درس و کاتلینی تره. 114 | 115 |
116 | 117 | ```kotlin 118 | val years = 10 119 | val message = "A decade is " + years + " years" 120 | val anotherMessage = "A decade is $years years" 121 | ``` 122 | 123 |
124 | 125 | اگر از همون روش دوم استفاده کردید و میخوایین از توابع داخلی اون متغییر استفاده کنید متونید این کار رو بکنید 126 | 127 |
128 | 129 | ```kotlin 130 | val name= "Mary" 131 | val anotherOne = "length of name is ${name.length}" 132 | ``` 133 | -------------------------------------------------------------------------------- /src/working-with-exceptions/README.md: -------------------------------------------------------------------------------- 1 |
2 | 3 | # کار کردن با exception ها 4 | 5 | پیشنهاد میشه این جلسه رو بر روی IntellJ IDEA امتحان کنید 6 | 7 | یکی از مشکلاتی که سعی میکنیم با کاتلین از بین ببریمش چک کردن Exception هاست. مثلاً در جاوا اگر یک متد بخواد Null Runtime Exception رو throw کنه باید صریحا بیان کنه. ایده پشت این قضیه اینه که توسعه دهنده ها بلاک های try-catch اشون رو بنویسن و خب اگه این اتفاق بیفته همه چیز فوق العاده میشه و برنامه بدون نقص اجرا میشه ولی خب توی واقعیت اینطور نیست. درواقع خیلی از توسعه دهنده ها کدهایی که باید مینوشتن رو نمینوشتن بنابراین توی توسعه زبان کاتلین از این موضوع چشم پوشی شد. خب بیاین یک نگاه به Exception ها بندازیم و ببینیم چجوری توی این زبون کار میکنن. 8 | 9 | یک کلاس درست میکنیم به نام NotANumberException و توش کد زیر رو میزنیم: 10 | 11 |
12 | 13 | ```kotlin 14 | class NotANumberException : Throwable() { 15 | 16 | } 17 | ``` 18 | 19 |
20 | 21 | در کاتلین کلاس پایه ای برای Exception ها کلاس Throwable است که اگر به سمت تعریفش هدایت بشین میبینین که کلاس ساده ای هستش که تنها دو خصیصه و چنتا constructor داره. 22 | 23 | • در IntelliJ IDEA برای هدایت شدن به سمت تعریف ، تنها لازم است که موشواره خود را بر روی نام عبارت برده و دکمه Ctrl را نگه داشته و بر روی آن کلیک کنید. 24 | 25 | و حالا برای این که بتونیم ازش استفاده کنیم تنها کاری که باید بکنیم اینه که کلاس NotANumberException رو throw کنم. 26 | 27 | 28 |
29 | 30 | ```kotlin 31 | class NotANumberException : Throwable() { 32 | 33 | } 34 | 35 | fun main(args: Array) { 36 | throw NotANumberException() 37 | } 38 | ``` 39 | 40 |
41 | 42 | و اگه این کد رو اجرا کنیم متوجه خواهیم شد که NotANumberException رو throw کردیم. 43 | 44 | حالا بیایم و یکم این سناریو رو طبیعی تر کنیم 45 | 46 |
47 | 48 | ```kotlin 49 | class NotANumberException : Throwable() { 50 | 51 | } 52 | 53 | fun checkIsNumber(obj: Any){ 54 | when(obj){ 55 | !is Int, Long, Float, Double -> throw NotANumberException() 56 | } 57 | } 58 | 59 | fun main(args: Array) { 60 | checkIsNumber("A") 61 | } 62 | ``` 63 | 64 |
65 | 66 | و همینطور که انتظار داریم اگه این برنامه رو اجرا کنیم 67 | 68 | 69 | 70 | میبینیم همون Exception مورد انتظارمون رو throw کرد. 71 | 72 | و خب اینجوری حالا میتونیم با try-catch این موضوع رو هندل کنیم 73 | 74 |
75 | 76 | ```kotlin 77 | class NotANumberException : Throwable() { 78 | 79 | } 80 | 81 | fun checkIsNumber(obj: Any){ 82 | when(obj){ 83 | !is Int, Long, Float, Double -> throw NotANumberException() 84 | } 85 | } 86 | 87 | fun main(args: Array) { 88 | 89 | try { 90 | checkIsNumber("A") 91 | } catch(e: NotANumberException) { 92 | println("It was not a number") 93 | } 94 | } 95 | ``` 96 | 97 |
98 | 99 | حالا بیایم یکم با try-catch بازی کنیم، مثلا از فایل یک مقدار بخونیم 100 | 101 | من توی شاخه ی اصلی یک فایل باز کردم به نام input.txt و داخلش یه متن کوچیک نوشتم. حالا میریم و یک سری خط کد مینویسم که از اون تابع بخونم. کدی که میزنیم خیلی از قسمتاش که مربوط به خوندن از فایل میشه که مهم نیست و خیلی شبیه جاواست: 102 | 103 |
104 | 105 | ```kotlin 106 | fun main(args: Array) { 107 | 108 | val buffer = BufferedReader(FileReader("input.txt")) 109 | try { 110 | val chars = CharArray(30) 111 | buffer.read(chars,0,40) 112 | }finally { 113 | println("Closing") 114 | buffer.close() 115 | } 116 | } 117 | ``` 118 | 119 |
120 | 121 | خودتون متوجه هستین که من سعی کردم باعث ایجاد مشکل بشم، چون دارم 40 خونه از یک بافری که 30 خونه بیشتر نداره میخونم. 122 | 123 | Finally در واقع همیشه انجام میشه، حتی اگر Exception هم بخوره. پس در واقع شما در اون قسمت مطمئنین حتی اگر هر چیز بدی هم اتفاق بیفته بازم این کد اجرا خواهد شد، پس میتونیم بسته شدن بافر رو توی اون قسمت قرار بدیم 124 | وحالا اگه برنامه رو اجرا کنیم میبینیم که 125 | 126 | 127 | 128 | ارور indexOutOfBoundException رو گرفتیم، چون همونطور که خودمون میدونستیم داریم 40 تا از یک آرایه 30 خونه ای میخونیم. ولی اگه دقت کنید، به هر حال Closing اجرا شده! 129 | 130 | اگه یادتون باشه از قسمت if، ماتونستیم یک عبارت شرطی رو به یک متغیر بدیم. با بلاک try-catch هم همینکار رو میتونیم انجام بدیم. 131 | 132 |
133 | 134 | ```kotlin 135 | fun main(args: Array) { 136 | val buffer = BufferedReader(FileReader("C:/Users/Darvishi/IdeaProject/KotlinFarsiRepo/src/input.txt")) 137 | val result = try { 138 | val chars = CharArray(30) 139 | buffer.read(chars,0,40) 140 | }catch (e: IndexOutOfBoundsException){ 141 | "Exception handled" 142 | }finally { 143 | println("Closing") 144 | buffer.close() 145 | } 146 | 147 | println(result) 148 | } 149 | ``` 150 | 151 |
152 | 153 | دقیقا به مانند if و when که اخرین خط مقدارش تعلق میگرفت به متغیر، اینجا هم اخرین خط مقدارش تعلق میگیره به متغیر. فقط یادتون باشه که مقادیر بلاک catch به متغیر تعلق میگیرند، نه مقادیر بلاک finally . 154 | 155 |
156 | -------------------------------------------------------------------------------- /src/working-with-exceptions/result-1.PNG: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/KotlinFarsi/OpenSourceTutorials-Introduction/92e9b633b82753deae74fa498e634a58c863e1d0/src/working-with-exceptions/result-1.PNG -------------------------------------------------------------------------------- /src/working-with-exceptions/result-2.PNG: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/KotlinFarsi/OpenSourceTutorials-Introduction/92e9b633b82753deae74fa498e634a58c863e1d0/src/working-with-exceptions/result-2.PNG -------------------------------------------------------------------------------- /src/working-with-nulls-from-java/README.md: -------------------------------------------------------------------------------- 1 |
2 | 3 | # کار کردن با null ها از جاوا 4 | 5 | ``` 6 | برای تمرین بهتر است از IntelliJ IDEA استفاده شود 7 | ``` 8 | 9 | یکی از ویژگی های کاتلین Null-Safe بودن این زبونه و دیدیم که بصورت پیشفرض تایپ ها نمیتونن null باشن و اگر میخواین که یک متغیر رو null کنین باید بیان کنین که اون nullable هه ولی خب زمانی که نوبت به همکاری با Java میرسه قضیه فرق میکنه، چراکه همه چی میتونه توی جاوا null باشه. خب اینجا باید چیکار کنیم؟ 10 | 11 | راستیتش قضیه خیلی سادست. به عبارتی برمیخوریم که ممکنه null باشه،خیلی ساده تنها از عملگر “?” استفاده میکنیم و تمام. یک مشکلی اینجا پیش میاد، مشکل که نه درواقع یک جور میشه گفت کدمون زشت میشه چرا که عبارتی خواهیم داشت که در اون به صورت تفریط از "?." استفاده شده، که این باعث میشه کدمون زشت بشه. برای حل این موضوع میتونیم از Annotation ها استفاده کنیم، بگیم که ما میدونیم که این عبارت ممکن نیست که null بشن و نیازی نداریم که از عملگری استفاده کنیم که این بازم مشکلات خودشو به وجود میاره. راه حل نهایی چیه ؟ درواقع زمانی که با جاوا کار میکنیم تصمیم نهایی با توسعه دهنده است که عبارت صدا زده شده این قابلیت رو داشته باشه که بتونه null باشه یا نه. 12 | 13 | بذارین با کد واضح تر براتون توضیح بدم. تا اینجا یادتون میاد که ما کلاسی به نام KotlinCustomRepo رو به صورت زیر ساختیم : 14 | 15 |
16 | 17 | ```kotlin 18 | class KotlinCustomerRepo : CustomerRepository { 19 | override fun getAll(): MutableList? { 20 | TODO("not implemented") 21 | } 22 | override fun getById(id: Int): CustomerJava? { 23 | TODO("not implemented") 24 | } 25 | } 26 | ``` 27 | 28 |
29 | 30 | ولی اگه من `?` رو پاک کنم بازم همه چیز درسته! 31 | 32 |
33 | 34 | ```kotlin 35 | class KotlinCustomerRepo : CustomerRepository { 36 | override fun getAll(): MutableList { 37 | TODO("not implemented") 38 | } 39 | override fun getById(id: Int): CustomerJava { 40 | TODO("not implemented") 41 | } 42 | } 43 | ``` 44 | 45 |
46 | 47 | و این درواقع دست توسعه دهنده است که به اون عبارت قابلیت داشتن null بده یا نه. 48 | 49 | بیاین بریم سراغ کلاس CustomerJava و دوتا متد به اون اضافه کنیم 50 | 51 |
52 | 53 | ```java 54 | public @NotNull String neverNull(){ 55 | return "A String"; 56 | } 57 | 58 | public String someTimesNull(){ 59 | return "A String"; 60 | } 61 | ``` 62 | 63 |
64 | 65 | برای متد اول از یکی از Annotation های IntelliJ استفاده کردیم که مشخص میکنه این عبارت null برنمیگردونه. (میتونه از Annotation های دیگه هم استفاده بشه) ولی دقیقا تفاوت این توی کاتلین چیه؟ تفاوت اینجاست که وقتی در یک کلاس کاتلین میخوایم از این توابع استفاده کنیم، کاتلین متوجه میشه که متد اول نمیتونه null باشه و این درحالیه که متد دوم رو nullable تصور میکنه. 66 | 67 |
68 | --------------------------------------------------------------------------------