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 |
--------------------------------------------------------------------------------