├── .gitignore ├── LICENSE.txt ├── README.md ├── build.gradle ├── gradle └── wrapper │ ├── gradle-wrapper.jar │ └── gradle-wrapper.properties ├── gradlew ├── gradlew.bat ├── instructor ├── advanced │ └── org │ │ └── jetbrains │ │ └── kotlinworkshop │ │ └── advanced │ │ ├── _10Asynchronous │ │ ├── 10_Timeout.kt │ │ ├── 11_Sequential.kt │ │ ├── 12_Concurrent.kt │ │ ├── 13_Lazy.kt │ │ ├── 14_Dispatchers.kt │ │ ├── 15_Channels.kt │ │ ├── 16_ClosingChannels.kt │ │ ├── 17_ProduceConsume.kt │ │ ├── 18_Pipeline.kt │ │ ├── 19_SharedState.kt │ │ ├── 1_LongRunningProcess.kt │ │ ├── 20_Actors.kt │ │ ├── 2_SuspendableComputation.kt │ │ ├── 3_SuspendableComputationLoop.kt │ │ ├── 4_SuspendableComputationSleep.kt │ │ ├── 5_SuspendableComputationDelay.kt │ │ ├── 6A_Comparison.kt │ │ ├── 6_SuspendableComputationJoin.kt │ │ ├── 7_WorkingWithJobs.kt │ │ ├── 8_NonCancellable.kt │ │ └── 9_Cancellable.kt │ │ ├── _1Object │ │ ├── _1Object.kt │ │ ├── _2CompanionObject.kt │ │ ├── _3JSingleton.java │ │ ├── _4UsingCompanionObjectFromJava.java │ │ └── _5UsingKotlinObjectFromJava.java │ │ ├── _2Interop │ │ ├── Session.java │ │ ├── UsingEmployee.java │ │ ├── UsingThrow.java │ │ ├── _1PlatformTypes.kt │ │ ├── _2ExtensionsFromJava.java │ │ ├── _3InteropAnnotations.kt │ │ └── _4Throws.kt │ │ ├── _3InlineFunctions │ │ ├── _1RunFunction.kt │ │ ├── _2LetFunction.kt │ │ ├── _3SynchronizedFunction.kt │ │ ├── _4TakeIfAndTakeUnlessFunctions.kt │ │ ├── _5RepeatFunction.kt │ │ └── _6NoInline.kt │ │ ├── _4Returns │ │ ├── _1NonLocalReturns.kt │ │ ├── _2LocalReturns.kt │ │ └── _3Nothing.kt │ │ ├── _5Reified │ │ ├── _1TypeErasure.kt │ │ ├── _2Reified.kt │ │ ├── _3FilterIsInstance.kt │ │ ├── _4ClassReferences.kt │ │ ├── _5Validators.kt │ │ └── _6RestrictionsOnReifiedTypeParameters.kt │ │ ├── _6LazyEvaluation │ │ ├── _1AsSequence.kt │ │ └── _2GenerateSequence.kt │ │ ├── _7FunctionalConstructs │ │ ├── _1AlgebraicDataTypes.kt │ │ ├── _2Currying.kt │ │ ├── _3Partials.kt │ │ ├── _4Composition.kt │ │ ├── _5Functors.kt │ │ ├── _6Applicatives.kt │ │ └── _7Monads.kt │ │ ├── _8Dsl │ │ ├── _1ExtensionWithInfix.kt │ │ ├── _2Invoke.kt │ │ ├── _3LambdasWithReceivers.kt │ │ ├── _4DslSample.kt │ │ └── _5HtmlExample.kt │ │ └── _9Metaprogramming │ │ ├── _1Annotations.kt │ │ ├── _2JavaReflection.kt │ │ └── _3KotlinReflection.kt ├── introduction │ ├── cmdline │ │ ├── Hello.class │ │ ├── Hello.java │ │ ├── HelloKt.class │ │ ├── Hellokt.jar │ │ ├── META-INF │ │ │ └── main.kotlin_module │ │ └── hello.kt │ └── org │ │ └── jetbrains │ │ └── kotlinworkshop │ │ └── introduction │ │ ├── _10Conventions │ │ └── _1OperatorOverloading.kt │ │ ├── _11Generics │ │ ├── _1Basics.kt │ │ ├── _2Invariance.kt │ │ ├── _3Covariance.kt │ │ └── _4Contravariance.kt │ │ ├── _1Intro │ │ ├── _0Main.kt │ │ ├── _1Variables.kt │ │ ├── _2Numbers.kt │ │ ├── _3Functions.kt │ │ ├── _4LocalFunctions.kt │ │ ├── _5Constants.kt │ │ ├── _6BasicInterop.kt │ │ └── _7FromJava.java │ │ ├── _2ControlStructures │ │ ├── _1IfAndWhen.kt │ │ ├── _2Loops.kt │ │ ├── _3Iterating.kt │ │ └── _4Ranges.kt │ │ ├── _3Classes │ │ ├── _10NestedClasses.kt │ │ ├── _11TypeAliases.kt │ │ ├── _1Classes.kt │ │ ├── _2PrimaryConstructor.kt │ │ ├── _3Constructors.kt │ │ ├── _4Properties.kt │ │ ├── _5MutableProperty.kt │ │ ├── _6Equals.kt │ │ ├── _7Tuples.kt │ │ ├── _8DataClass.kt │ │ ├── _9Destructuring.kt │ │ └── javaCode │ │ │ ├── Person.java │ │ │ └── Rectangle.java │ │ ├── _4Hierarchies │ │ ├── _1Interfaces.kt │ │ ├── _2AbstractClasses.kt │ │ └── _3ClassInheritance.kt │ │ ├── _5Nullability │ │ ├── _1Nullability.kt │ │ ├── _2Safecast.kt │ │ └── _3LateInit.kt │ │ ├── _6Extensions │ │ └── _1Extensions.kt │ │ ├── _7Lambdas │ │ ├── _1HigherOrder.kt │ │ ├── _2Lambdas.kt │ │ ├── _3DestructuringInLambdas.kt │ │ └── _4AnonymousFunctions.kt │ │ ├── _8Delegation │ │ ├── _1ClassDelegation.kt │ │ ├── _2LazyProperty.kt │ │ ├── _3Observable.kt │ │ └── _4CustomDelegation.kt │ │ ├── _9Functional │ │ ├── _1ListOperators.kt │ │ ├── _2Folds.kt │ │ ├── _3RefactoringFunctional.kt │ │ ├── _4RemovingState.kt │ │ ├── _5TransformingData.kt │ │ ├── _6VariousPatterns.kt │ │ ├── _7TailRecursion.kt │ │ └── _8Memoisation.kt │ │ └── _Shared │ │ ├── AlbumData.kt │ │ ├── Customer.kt │ │ ├── CustomerJava.java │ │ └── CustomerRepository.kt └── quizzes │ └── org │ └── jetbrains │ └── kotlinworkshop │ └── quizzes │ ├── _1Intro │ ├── _1IntroTasks.kt │ └── _2Foo.kt │ ├── _2Extensions │ ├── Extensions.kt │ ├── MemberVsExtension.kt │ ├── ParentVsChild.kt │ ├── ParentVsChildJava.java │ ├── RepeatExample.kt │ └── UsingRepeatFromJava.java │ ├── _3Classes │ ├── Evaluation.kt │ ├── Foo.kt │ ├── InnerAndNested.kt │ ├── Person.kt │ ├── UsePersonFromJava.java │ └── Visibility.kt │ ├── _4Nullability │ ├── Lists.kt │ ├── Name.kt │ ├── SafeCasts.kt │ └── isNullOrEmpty.kt │ ├── _5TypeSystem │ ├── JavaClass.java │ ├── Parent.java │ ├── Subclass.java │ ├── Usage.java │ ├── _1NPE.kt │ ├── _2ExplicitTypeSpecification.kt │ ├── _2NullInList.kt │ └── _3NPEDuringInitialization.kt │ ├── _6Lambdas │ └── Heroes.kt │ └── _7InlineAndLazyIteration │ ├── Inline.kt │ ├── IntermediateCollections.kt │ └── LazyIteration.kt ├── jetbrainslogo.png ├── kotlinlogo.png ├── settings.gradle └── student ├── tasks └── org │ └── jetbrains │ └── kotlinworkshop │ └── student │ └── single │ ├── _0Nullability │ ├── MessageUtil.java │ └── Task.kt │ ├── _1BreakingSafety │ ├── JavaClass.java │ ├── _1NPE.kt │ ├── _2NullInList.kt │ ├── _3NotImmutableProperty.kt │ └── _4NPEDuringInitialization.kt │ ├── _2Shop │ ├── JavaCode.java │ ├── _10GroupBy.kt │ ├── _11Partition.kt │ ├── _12Fold.kt │ ├── _13CompoundTasks.kt │ ├── _14SmthWithCollections.kt │ ├── _1Introduction.kt │ ├── _2FilterMap.kt │ ├── _3AllAnyAndOtherPredicates.kt │ ├── _4FlatMap.kt │ ├── _5MaxMin.kt │ ├── _6Sort.kt │ ├── _7Sum.kt │ ├── _8Zip.kt │ ├── _9AssociateBy.kt │ └── shop.kt │ ├── _3HtmlBuilders │ ├── Task.kt │ ├── data.kt │ ├── html.kt │ └── htmlDemo.kt │ ├── _3TaxiPark │ ├── TaxiPark.kt │ ├── _1FakeDrivers.kt │ ├── _2FaithfulPassengers.kt │ ├── _3FrequentPassengers.kt │ ├── _4SmartPassengers.kt │ ├── _5FrequentTripDuration.kt │ └── _6TestParetoPrinciple.kt │ ├── _4Generics │ └── GenericFunctions.kt │ ├── _5LazyProperty │ └── LazyProperty.kt │ ├── _6WithApply │ └── UsingWithApplyFunctions.kt │ ├── _7CreatingDsl │ ├── BreakfastMenu.kt │ ├── BreakfastMenuBonusTask.kt │ ├── breakfastMenu.xml │ └── createBreakfastMenu.kt │ └── _8Conventions │ ├── MyDate.kt │ ├── MyDateUsage.kt │ └── MyDateUtil.kt └── tests └── org └── jetbrains └── kotlinworkshop └── student └── single ├── _0Nullability └── TestSendMessage.kt ├── _1BreakingSafety ├── _1TestNPE.kt ├── _2TestNullInList.kt ├── _3TestNotImmutableProperty.kt └── _4TestNPEDuringInitialization.kt ├── _2Shop ├── ShopBuilders.kt ├── TestShop.kt ├── _10GroupBy.kt ├── _11Partition.kt ├── _12Fold.kt ├── _13CompoundTasks.kt ├── _14SmthWithCollections.kt ├── _1Introduction.kt ├── _2FilterMap.kt ├── _3AllAnyAndOtherPredicates.kt ├── _4FlatMap.kt ├── _5MaxMin.kt ├── _6Sort.kt ├── _7Sum.kt ├── _8Zip.kt └── _9AssociateBy.kt ├── _3HtmlBuilders └── TestHtmlBuilders.kt ├── _3TaxiPark ├── TestTaxiParkUtil.kt ├── _1TestFakeDrivers.kt ├── _2TestFaithfulPassengers.kt ├── _3TestFrequentPassengers.kt ├── _4TestSmartPassengers.kt ├── _5FrequentTripDuration.kt └── _6TestParetoPrinciple.kt ├── _4Generics └── TestGenericFunction.kt ├── _5LazyProperty └── TestLazyProperty.kt ├── _6WithApply └── TestUsingWithApplyFunctions.kt ├── _7CreatingDsl └── TestBreakfastMenuCreation.kt └── _8Conventions ├── DateUtil.kt ├── TestTask1.kt ├── TestTask2.kt ├── TestTask3.kt └── TestTask4And5.kt /.gitignore: -------------------------------------------------------------------------------- 1 | *.iws 2 | .ds_store 3 | out/ 4 | .idea 5 | .idea_modules/ 6 | .gradle/ 7 | .idea/ 8 | build/ 9 | presources/ 10 | -------------------------------------------------------------------------------- /LICENSE.txt: -------------------------------------------------------------------------------- 1 | Creative Commons Attribution-ShareAlike 4.0 International Public 2 | License 3 | 4 | By exercising the Licensed Rights (defined below), You accept and agree 5 | to be bound by the terms and conditions of this Creative Commons 6 | Attribution-ShareAlike 4.0 International Public License ("Public 7 | License"). To the extent this Public License may be interpreted as a 8 | contract, You are granted the Licensed Rights in consideration of Your 9 | acceptance of these terms and conditions, and the Licensor grants You 10 | such rights in consideration of benefits the Licensor receives from 11 | making the Licensed Material available under these terms and 12 | conditions. 13 | 14 | 15 | Section 1 -- Definitions. 16 | 17 | a. Adapted Material means material subject to Copyright and Similar 18 | Rights that is derived from or based upon the Licensed Material 19 | and in which the Licensed Material is translated, altered, 20 | arranged, transformed, or otherwise modified in a manner requiring 21 | permission under the Copyright and Similar Rights held by the 22 | Licensor. For purposes of this Public License, where the Licensed 23 | Material is a musical work, performance, or sound recording, 24 | Adapted Material is always produced where the Licensed Material is 25 | synched in timed relation with a moving image. 26 | 27 | b. Adapter's License means the license You apply to Your Copyright 28 | and Similar Rights in Your contributions to Adapted Material in 29 | accordance with the terms and conditions of this Public License. 30 | 31 | c. BY-SA Compatible License means a license listed at 32 | creativecommons.org/compatiblelicenses, approved by Creative 33 | Commons as essentially the equivalent of this Public License. 34 | 35 | d. Copyright and Similar Rights means copyright and/or similar rights 36 | closely related to copyright including, without limitation, 37 | performance, broadcast, sound recording, and Sui Generis Database 38 | Rights, without regard to how the rights are labeled or 39 | categorized. For purposes of this Public License, the rights 40 | specified in Section 2(b)(1)-(2) are not Copyright and Similar 41 | Rights. 42 | 43 | e. Effective Technological Measures means those measures that, in the 44 | absence of proper authority, may not be circumvented under laws 45 | fulfilling obligations under Article 11 of the WIPO Copyright 46 | Treaty adopted on December 20, 1996, and/or similar international 47 | agreements. 48 | 49 | f. Exceptions and Limitations means fair use, fair dealing, and/or 50 | any other exception or limitation to Copyright and Similar Rights 51 | that applies to Your use of the Licensed Material. 52 | 53 | g. License Elements means the license attributes listed in the name 54 | of a Creative Commons Public License. The License Elements of this 55 | Public License are Attribution and ShareAlike. 56 | 57 | h. Licensed Material means the artistic or literary work, database, 58 | or other material to which the Licensor applied this Public 59 | License. 60 | 61 | i. Licensed Rights means the rights granted to You subject to the 62 | terms and conditions of this Public License, which are limited to 63 | all Copyright and Similar Rights that apply to Your use of the 64 | Licensed Material and that the Licensor has authority to license. 65 | 66 | j. Licensor means the individual(s) or entity(ies) granting rights 67 | under this Public License. 68 | 69 | k. Share means to provide material to the public by any means or 70 | process that requires permission under the Licensed Rights, such 71 | as reproduction, public display, public performance, distribution, 72 | dissemination, communication, or importation, and to make material 73 | available to the public including in ways that members of the 74 | public may access the material from a place and at a time 75 | individually chosen by them. 76 | 77 | l. Sui Generis Database Rights means rights other than copyright 78 | resulting from Directive 96/9/EC of the European Parliament and of 79 | the Council of 11 March 1996 on the legal protection of databases, 80 | as amended and/or succeeded, as well as other essentially 81 | equivalent rights anywhere in the world. 82 | 83 | m. You means the individual or entity exercising the Licensed Rights 84 | under this Public License. Your has a corresponding meaning. 85 | 86 | 87 | Section 2 -- Scope. 88 | 89 | a. License grant. 90 | 91 | 1. Subject to the terms and conditions of this Public License, 92 | the Licensor hereby grants You a worldwide, royalty-free, 93 | non-sublicensable, non-exclusive, irrevocable license to 94 | exercise the Licensed Rights in the Licensed Material to: 95 | 96 | a. reproduce and Share the Licensed Material, in whole or 97 | in part; and 98 | 99 | b. produce, reproduce, and Share Adapted Material. 100 | 101 | 2. Exceptions and Limitations. For the avoidance of doubt, where 102 | Exceptions and Limitations apply to Your use, this Public 103 | License does not apply, and You do not need to comply with 104 | its terms and conditions. 105 | 106 | 3. Term. The term of this Public License is specified in Section 107 | 6(a). 108 | 109 | 4. Media and formats; technical modifications allowed. The 110 | Licensor authorizes You to exercise the Licensed Rights in 111 | all media and formats whether now known or hereafter created, 112 | and to make technical modifications necessary to do so. The 113 | Licensor waives and/or agrees not to assert any right or 114 | authority to forbid You from making technical modifications 115 | necessary to exercise the Licensed Rights, including 116 | technical modifications necessary to circumvent Effective 117 | Technological Measures. For purposes of this Public License, 118 | simply making modifications authorized by this Section 2(a) 119 | (4) never produces Adapted Material. 120 | 121 | 5. Downstream recipients. 122 | 123 | a. Offer from the Licensor -- Licensed Material. Every 124 | recipient of the Licensed Material automatically 125 | receives an offer from the Licensor to exercise the 126 | Licensed Rights under the terms and conditions of this 127 | Public License. 128 | 129 | b. Additional offer from the Licensor -- Adapted Material. 130 | Every recipient of Adapted Material from You 131 | automatically receives an offer from the Licensor to 132 | exercise the Licensed Rights in the Adapted Material 133 | under the conditions of the Adapter's License You apply. 134 | 135 | c. No downstream restrictions. You may not offer or impose 136 | any additional or different terms or conditions on, or 137 | apply any Effective Technological Measures to, the 138 | Licensed Material if doing so restricts exercise of the 139 | Licensed Rights by any recipient of the Licensed 140 | Material. 141 | 142 | 6. No endorsement. Nothing in this Public License constitutes or 143 | may be construed as permission to assert or imply that You 144 | are, or that Your use of the Licensed Material is, connected 145 | with, or sponsored, endorsed, or granted official status by, 146 | the Licensor or others designated to receive attribution as 147 | provided in Section 3(a)(1)(A)(i). 148 | 149 | b. Other rights. 150 | 151 | 1. Moral rights, such as the right of integrity, are not 152 | licensed under this Public License, nor are publicity, 153 | privacy, and/or other similar personality rights; however, to 154 | the extent possible, the Licensor waives and/or agrees not to 155 | assert any such rights held by the Licensor to the limited 156 | extent necessary to allow You to exercise the Licensed 157 | Rights, but not otherwise. 158 | 159 | 2. Patent and trademark rights are not licensed under this 160 | Public License. 161 | 162 | 3. To the extent possible, the Licensor waives any right to 163 | collect royalties from You for the exercise of the Licensed 164 | Rights, whether directly or through a collecting society 165 | under any voluntary or waivable statutory or compulsory 166 | licensing scheme. In all other cases the Licensor expressly 167 | reserves any right to collect such royalties. 168 | 169 | 170 | Section 3 -- License Conditions. 171 | 172 | Your exercise of the Licensed Rights is expressly made subject to the 173 | following conditions. 174 | 175 | a. Attribution. 176 | 177 | 1. If You Share the Licensed Material (including in modified 178 | form), You must: 179 | 180 | a. retain the following if it is supplied by the Licensor 181 | with the Licensed Material: 182 | 183 | i. identification of the creator(s) of the Licensed 184 | Material and any others designated to receive 185 | attribution, in any reasonable manner requested by 186 | the Licensor (including by pseudonym if 187 | designated); 188 | 189 | ii. a copyright notice; 190 | 191 | iii. a notice that refers to this Public License; 192 | 193 | iv. a notice that refers to the disclaimer of 194 | warranties; 195 | 196 | v. a URI or hyperlink to the Licensed Material to the 197 | extent reasonably practicable; 198 | 199 | b. indicate if You modified the Licensed Material and 200 | retain an indication of any previous modifications; and 201 | 202 | c. indicate the Licensed Material is licensed under this 203 | Public License, and include the text of, or the URI or 204 | hyperlink to, this Public License. 205 | 206 | 2. You may satisfy the conditions in Section 3(a)(1) in any 207 | reasonable manner based on the medium, means, and context in 208 | which You Share the Licensed Material. For example, it may be 209 | reasonable to satisfy the conditions by providing a URI or 210 | hyperlink to a resource that includes the required 211 | information. 212 | 213 | 3. If requested by the Licensor, You must remove any of the 214 | information required by Section 3(a)(1)(A) to the extent 215 | reasonably practicable. 216 | 217 | b. ShareAlike. 218 | 219 | In addition to the conditions in Section 3(a), if You Share 220 | Adapted Material You produce, the following conditions also apply. 221 | 222 | 1. The Adapter's License You apply must be a Creative Commons 223 | license with the same License Elements, this version or 224 | later, or a BY-SA Compatible License. 225 | 226 | 2. You must include the text of, or the URI or hyperlink to, the 227 | Adapter's License You apply. You may satisfy this condition 228 | in any reasonable manner based on the medium, means, and 229 | context in which You Share Adapted Material. 230 | 231 | 3. You may not offer or impose any additional or different terms 232 | or conditions on, or apply any Effective Technological 233 | Measures to, Adapted Material that restrict exercise of the 234 | rights granted under the Adapter's License You apply. 235 | 236 | 237 | Section 4 -- Sui Generis Database Rights. 238 | 239 | Where the Licensed Rights include Sui Generis Database Rights that 240 | apply to Your use of the Licensed Material: 241 | 242 | a. for the avoidance of doubt, Section 2(a)(1) grants You the right 243 | to extract, reuse, reproduce, and Share all or a substantial 244 | portion of the contents of the database; 245 | 246 | b. if You include all or a substantial portion of the database 247 | contents in a database in which You have Sui Generis Database 248 | Rights, then the database in which You have Sui Generis Database 249 | Rights (but not its individual contents) is Adapted Material, 250 | including for purposes of Section 3(b); and 251 | 252 | c. You must comply with the conditions in Section 3(a) if You Share 253 | all or a substantial portion of the contents of the database. 254 | 255 | For the avoidance of doubt, this Section 4 supplements and does not 256 | replace Your obligations under this Public License where the Licensed 257 | Rights include other Copyright and Similar Rights. 258 | 259 | 260 | Section 5 -- Disclaimer of Warranties and Limitation of Liability. 261 | 262 | a. UNLESS OTHERWISE SEPARATELY UNDERTAKEN BY THE LICENSOR, TO THE 263 | EXTENT POSSIBLE, THE LICENSOR OFFERS THE LICENSED MATERIAL AS-IS 264 | AND AS-AVAILABLE, AND MAKES NO REPRESENTATIONS OR WARRANTIES OF 265 | ANY KIND CONCERNING THE LICENSED MATERIAL, WHETHER EXPRESS, 266 | IMPLIED, STATUTORY, OR OTHER. THIS INCLUDES, WITHOUT LIMITATION, 267 | WARRANTIES OF TITLE, MERCHANTABILITY, FITNESS FOR A PARTICULAR 268 | PURPOSE, NON-INFRINGEMENT, ABSENCE OF LATENT OR OTHER DEFECTS, 269 | ACCURACY, OR THE PRESENCE OR ABSENCE OF ERRORS, WHETHER OR NOT 270 | KNOWN OR DISCOVERABLE. WHERE DISCLAIMERS OF WARRANTIES ARE NOT 271 | ALLOWED IN FULL OR IN PART, THIS DISCLAIMER MAY NOT APPLY TO YOU. 272 | 273 | b. TO THE EXTENT POSSIBLE, IN NO EVENT WILL THE LICENSOR BE LIABLE 274 | TO YOU ON ANY LEGAL THEORY (INCLUDING, WITHOUT LIMITATION, 275 | NEGLIGENCE) OR OTHERWISE FOR ANY DIRECT, SPECIAL, INDIRECT, 276 | INCIDENTAL, CONSEQUENTIAL, PUNITIVE, EXEMPLARY, OR OTHER LOSSES, 277 | COSTS, EXPENSES, OR DAMAGES ARISING OUT OF THIS PUBLIC LICENSE OR 278 | USE OF THE LICENSED MATERIAL, EVEN IF THE LICENSOR HAS BEEN 279 | ADVISED OF THE POSSIBILITY OF SUCH LOSSES, COSTS, EXPENSES, OR 280 | DAMAGES. WHERE A LIMITATION OF LIABILITY IS NOT ALLOWED IN FULL OR 281 | IN PART, THIS LIMITATION MAY NOT APPLY TO YOU. 282 | 283 | c. The disclaimer of warranties and limitation of liability provided 284 | above shall be interpreted in a manner that, to the extent 285 | possible, most closely approximates an absolute disclaimer and 286 | waiver of all liability. 287 | 288 | 289 | Section 6 -- Term and Termination. 290 | 291 | a. This Public License applies for the term of the Copyright and 292 | Similar Rights licensed here. However, if You fail to comply with 293 | this Public License, then Your rights under this Public License 294 | terminate automatically. 295 | 296 | b. Where Your right to use the Licensed Material has terminated under 297 | Section 6(a), it reinstates: 298 | 299 | 1. automatically as of the date the violation is cured, provided 300 | it is cured within 30 days of Your discovery of the 301 | violation; or 302 | 303 | 2. upon express reinstatement by the Licensor. 304 | 305 | For the avoidance of doubt, this Section 6(b) does not affect any 306 | right the Licensor may have to seek remedies for Your violations 307 | of this Public License. 308 | 309 | c. For the avoidance of doubt, the Licensor may also offer the 310 | Licensed Material under separate terms or conditions or stop 311 | distributing the Licensed Material at any time; however, doing so 312 | will not terminate this Public License. 313 | 314 | d. Sections 1, 5, 6, 7, and 8 survive termination of this Public 315 | License. 316 | 317 | 318 | Section 7 -- Other Terms and Conditions. 319 | 320 | a. The Licensor shall not be bound by any additional or different 321 | terms or conditions communicated by You unless expressly agreed. 322 | 323 | b. Any arrangements, understandings, or agreements regarding the 324 | Licensed Material not stated herein are separate from and 325 | independent of the terms and conditions of this Public License. 326 | 327 | 328 | Section 8 -- Interpretation. 329 | 330 | a. For the avoidance of doubt, this Public License does not, and 331 | shall not be interpreted to, reduce, limit, restrict, or impose 332 | conditions on any use of the Licensed Material that could lawfully 333 | be made without permission under this Public License. 334 | 335 | b. To the extent possible, if any provision of this Public License is 336 | deemed unenforceable, it shall be automatically reformed to the 337 | minimum extent necessary to make it enforceable. If the provision 338 | cannot be reformed, it shall be severed from this Public License 339 | without affecting the enforceability of the remaining terms and 340 | conditions. 341 | 342 | c. No term or condition of this Public License will be waived and no 343 | failure to comply consented to unless expressly agreed to by the 344 | Licensor. 345 | 346 | d. Nothing in this Public License constitutes or may be interpreted 347 | as a limitation upon, or waiver of, any privileges and immunities 348 | that apply to the Licensor or You, including from the legal 349 | processes of any jurisdiction or authority. 350 | 351 | -------------------------------------------------------------------------------- /README.md: -------------------------------------------------------------------------------- 1 | [![official project](http://jb.gg/badges/official-plastic.svg)](https://confluence.jetbrains.com/display/ALL/JetBrains+on+GitHub) 2 | 3 | ## Kotlin Workshop 4 | 5 | ![Kotlin Logo](kotlinlogo.png) 6 | 7 | A Kotlin workshop intended to be taught in two days. 8 | 9 | ### Structure 10 | 11 | This workshop is divided into two parts 12 | 13 | * Introduction to Kotlin 14 | * Advanced Kotlin 15 | 16 | It consists of 17 | 18 | * **Instructor Project**: Used to explain concepts, with existing code samples 19 | * **Student Project**: For students to complete 20 | * **Presentations**: For the instructor to use 21 | * **Questions**: For students to complete 22 | 23 | Both the Instructor Project and the slides have Introduction and Advanced modules included. While the Introduction 24 | has a lot of pre-built examples, it also serves as a canvas to show more code while teaching. However, please make sure that if you're 25 | a contributing author to this project, that you *do not* check-in any ad-hoc code. It's also recommended to use Scratch files in IntelliJ IDEA 26 | for this purpose. 27 | 28 | #### Presentations 29 | 30 | Slides for the workshop lead by Hadi Hariri can be found [here](https://docs.google.com/presentation/d/1zYWyDedyf0YhnLFF3TVpUqU3C8PKTuvR5P06L99MRn8/edit?usp=sharing). 31 | 32 | Presentations used for the workshop at KotlinConf: 33 | 1. [Intro](https://speakerdeck.com/svtk/1-intro-kotlin-workshop) 34 | 2. [Nullable Types](https://speakerdeck.com/svtk/2-nullable-types-in-kotlin-kotlin-workshop) 35 | 3. [Object-Oriented Programming in Kotlin](https://speakerdeck.com/svtk/3-object-oriented-programming-in-kotlin-kotlin-workshop) 36 | 4. [Kotlin Types](https://speakerdeck.com/svtk/4-kotlin-types-kotlin-workshop) 37 | 5. [Functional Programming in Kotlin](https://speakerdeck.com/svtk/5-functional-programming-kotlin-workshop) 38 | 6. [The Power of inline](https://speakerdeck.com/svtk/6-the-power-of-inline-kotlin-workshop) 39 | 7. [Lambda With Receiver](https://speakerdeck.com/svtk/7-lambda-with-receiver-kotlin-workshop) 40 | 8. [Conventions](https://speakerdeck.com/svtk/8-conventions-kotlin-workshop) 41 | 9. [Intro to Coroutines](https://speakerdeck.com/svtk/9-introduction-to-coroutines-kotlin-workshop) 42 | 43 | #### Questions 44 | 45 | Questions can be found [here](https://drive.google.com/file/d/18AiXqEzdJmNonc6Lo6eumeFmcVvC_9vk/view?usp=sharing). The keys to the questions are in the module `instructor/quizzes`. 46 | 47 | Note that the similar material can be found explained in detail in the following [Coursera course](https://www.coursera.org/learn/kotlin-for-java-developers). 48 | 49 | ### Authors 50 | 51 | This workshop includes material from the following authors: 52 | 53 | * [Hadi Hariri](https://github.com/hhariri) 54 | * [Svetlana Isakova](https://github.com/svtk) 55 | * [Dmitry Jemerov](https://github.com/yole) 56 | * [Roman Elizarov](https://github.com/elizarov) 57 | 58 | ### License and Usage 59 | 60 | The material provided in this repository, including but not limited to source code, presentations, notes and exercises is Copyright (c) 2017 JetBrains, and is provided as-is. 61 | 62 | ![JetBrains Logo](jetbrainslogo.png) 63 | 64 | Creative Commons License
This work is licensed under a Creative Commons Attribution-ShareAlike 4.0 International License. 65 | 66 | 67 | JetBrains and Kotlin are Registered Trademarks of their respective trademark holders. 68 | 69 | #### Contributions 70 | 71 | We welcome all contributions to this workshop. If you feel you'd like to contribute something, create a fork and make a pull request. Bug fixes, comments, suggestions, all welcome. 72 | 73 | If you're contributing code or samples, please send a pull request. If you'd like to update the slides or questions, please contact [Hadi Hariri](https://github.com/hhariri). 74 | 75 | #### Usage and endorsements 76 | 77 | You are welcome to use the material in this workshop provided you abide by the corresponding license agreement. Additionally 78 | 79 | * By using this material, with or without any modification, JetBrains does not endorse any workshop or training that you may offer. 80 | * By using this material, with or without any modification, you may not use JetBrain's name to promote your workshop or training without prior written consent. 81 | * By using this material, provided there are no modifications, you may indicate that you are using JetBrains Kotlin Workshop Material. 82 | 83 | If you're interested in becoming an official JetBrains Training Partner, please [contact us](https://www.jetbrains.com/company/partners/become_a_partner.html) 84 | -------------------------------------------------------------------------------- /build.gradle: -------------------------------------------------------------------------------- 1 | plugins { 2 | id 'java' 3 | id 'org.jetbrains.kotlin.jvm' version '1.3.21' 4 | } 5 | 6 | group 'org.jetbrains.kotlin-workshop' 7 | version '1.0-SNAPSHOT' 8 | 9 | sourceCompatibility = 1.8 10 | 11 | repositories { 12 | mavenCentral() 13 | } 14 | 15 | dependencies { 16 | compile "org.jetbrains.kotlin:kotlin-stdlib-jdk8" 17 | compile "org.jetbrains.kotlin:kotlin-reflect" 18 | compile 'org.jetbrains.kotlinx:kotlinx-coroutines-core:1.1.1' 19 | 20 | testCompile 'org.junit.jupiter:junit-jupiter-engine:5.4.0' 21 | testCompile "org.jetbrains.kotlin:kotlin-test-junit5" 22 | } 23 | 24 | compileKotlin { 25 | kotlinOptions.jvmTarget = "1.8" 26 | } 27 | compileTestKotlin { 28 | kotlinOptions.jvmTarget = "1.8" 29 | } 30 | sourceSets { 31 | main.kotlin.srcDirs += 'instructor/introduction' 32 | main.kotlin.srcDirs += 'instructor/advanced' 33 | main.kotlin.srcDirs += 'instructor/quizzes' 34 | main.kotlin.srcDirs += 'student/tasks' 35 | test.kotlin.srcDirs += 'student/tests' 36 | } -------------------------------------------------------------------------------- /gradle/wrapper/gradle-wrapper.jar: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/Kotlin/workshop/37552440e6e6a1f7607ea5722eef1e8d5578d4f5/gradle/wrapper/gradle-wrapper.jar -------------------------------------------------------------------------------- /gradle/wrapper/gradle-wrapper.properties: -------------------------------------------------------------------------------- 1 | distributionBase=GRADLE_USER_HOME 2 | distributionPath=wrapper/dists 3 | zipStoreBase=GRADLE_USER_HOME 4 | zipStorePath=wrapper/dists 5 | distributionUrl=https\://services.gradle.org/distributions/gradle-4.10-all.zip 6 | -------------------------------------------------------------------------------- /gradlew: -------------------------------------------------------------------------------- 1 | #!/usr/bin/env sh 2 | 3 | ############################################################################## 4 | ## 5 | ## Gradle start up script for UN*X 6 | ## 7 | ############################################################################## 8 | 9 | # Attempt to set APP_HOME 10 | # Resolve links: $0 may be a link 11 | PRG="$0" 12 | # Need this for relative symlinks. 13 | while [ -h "$PRG" ] ; do 14 | ls=`ls -ld "$PRG"` 15 | link=`expr "$ls" : '.*-> \(.*\)$'` 16 | if expr "$link" : '/.*' > /dev/null; then 17 | PRG="$link" 18 | else 19 | PRG=`dirname "$PRG"`"/$link" 20 | fi 21 | done 22 | SAVED="`pwd`" 23 | cd "`dirname \"$PRG\"`/" >/dev/null 24 | APP_HOME="`pwd -P`" 25 | cd "$SAVED" >/dev/null 26 | 27 | APP_NAME="Gradle" 28 | APP_BASE_NAME=`basename "$0"` 29 | 30 | # Add default JVM options here. You can also use JAVA_OPTS and GRADLE_OPTS to pass JVM options to this script. 31 | DEFAULT_JVM_OPTS="" 32 | 33 | # Use the maximum available, or set MAX_FD != -1 to use that value. 34 | MAX_FD="maximum" 35 | 36 | warn () { 37 | echo "$*" 38 | } 39 | 40 | die () { 41 | echo 42 | echo "$*" 43 | echo 44 | exit 1 45 | } 46 | 47 | # OS specific support (must be 'true' or 'false'). 48 | cygwin=false 49 | msys=false 50 | darwin=false 51 | nonstop=false 52 | case "`uname`" in 53 | CYGWIN* ) 54 | cygwin=true 55 | ;; 56 | Darwin* ) 57 | darwin=true 58 | ;; 59 | MINGW* ) 60 | msys=true 61 | ;; 62 | NONSTOP* ) 63 | nonstop=true 64 | ;; 65 | esac 66 | 67 | CLASSPATH=$APP_HOME/gradle/wrapper/gradle-wrapper.jar 68 | 69 | # Determine the Java command to use to start the JVM. 70 | if [ -n "$JAVA_HOME" ] ; then 71 | if [ -x "$JAVA_HOME/jre/sh/java" ] ; then 72 | # IBM's JDK on AIX uses strange locations for the executables 73 | JAVACMD="$JAVA_HOME/jre/sh/java" 74 | else 75 | JAVACMD="$JAVA_HOME/bin/java" 76 | fi 77 | if [ ! -x "$JAVACMD" ] ; then 78 | die "ERROR: JAVA_HOME is set to an invalid directory: $JAVA_HOME 79 | 80 | Please set the JAVA_HOME variable in your environment to match the 81 | location of your Java installation." 82 | fi 83 | else 84 | JAVACMD="java" 85 | which java >/dev/null 2>&1 || die "ERROR: JAVA_HOME is not set and no 'java' command could be found in your PATH. 86 | 87 | Please set the JAVA_HOME variable in your environment to match the 88 | location of your Java installation." 89 | fi 90 | 91 | # Increase the maximum file descriptors if we can. 92 | if [ "$cygwin" = "false" -a "$darwin" = "false" -a "$nonstop" = "false" ] ; then 93 | MAX_FD_LIMIT=`ulimit -H -n` 94 | if [ $? -eq 0 ] ; then 95 | if [ "$MAX_FD" = "maximum" -o "$MAX_FD" = "max" ] ; then 96 | MAX_FD="$MAX_FD_LIMIT" 97 | fi 98 | ulimit -n $MAX_FD 99 | if [ $? -ne 0 ] ; then 100 | warn "Could not set maximum file descriptor limit: $MAX_FD" 101 | fi 102 | else 103 | warn "Could not query maximum file descriptor limit: $MAX_FD_LIMIT" 104 | fi 105 | fi 106 | 107 | # For Darwin, add options to specify how the application appears in the dock 108 | if $darwin; then 109 | GRADLE_OPTS="$GRADLE_OPTS \"-Xdock:name=$APP_NAME\" \"-Xdock:icon=$APP_HOME/media/gradle.icns\"" 110 | fi 111 | 112 | # For Cygwin, switch paths to Windows format before running java 113 | if $cygwin ; then 114 | APP_HOME=`cygpath --path --mixed "$APP_HOME"` 115 | CLASSPATH=`cygpath --path --mixed "$CLASSPATH"` 116 | JAVACMD=`cygpath --unix "$JAVACMD"` 117 | 118 | # We build the pattern for arguments to be converted via cygpath 119 | ROOTDIRSRAW=`find -L / -maxdepth 1 -mindepth 1 -type d 2>/dev/null` 120 | SEP="" 121 | for dir in $ROOTDIRSRAW ; do 122 | ROOTDIRS="$ROOTDIRS$SEP$dir" 123 | SEP="|" 124 | done 125 | OURCYGPATTERN="(^($ROOTDIRS))" 126 | # Add a user-defined pattern to the cygpath arguments 127 | if [ "$GRADLE_CYGPATTERN" != "" ] ; then 128 | OURCYGPATTERN="$OURCYGPATTERN|($GRADLE_CYGPATTERN)" 129 | fi 130 | # Now convert the arguments - kludge to limit ourselves to /bin/sh 131 | i=0 132 | for arg in "$@" ; do 133 | CHECK=`echo "$arg"|egrep -c "$OURCYGPATTERN" -` 134 | CHECK2=`echo "$arg"|egrep -c "^-"` ### Determine if an option 135 | 136 | if [ $CHECK -ne 0 ] && [ $CHECK2 -eq 0 ] ; then ### Added a condition 137 | eval `echo args$i`=`cygpath --path --ignore --mixed "$arg"` 138 | else 139 | eval `echo args$i`="\"$arg\"" 140 | fi 141 | i=$((i+1)) 142 | done 143 | case $i in 144 | (0) set -- ;; 145 | (1) set -- "$args0" ;; 146 | (2) set -- "$args0" "$args1" ;; 147 | (3) set -- "$args0" "$args1" "$args2" ;; 148 | (4) set -- "$args0" "$args1" "$args2" "$args3" ;; 149 | (5) set -- "$args0" "$args1" "$args2" "$args3" "$args4" ;; 150 | (6) set -- "$args0" "$args1" "$args2" "$args3" "$args4" "$args5" ;; 151 | (7) set -- "$args0" "$args1" "$args2" "$args3" "$args4" "$args5" "$args6" ;; 152 | (8) set -- "$args0" "$args1" "$args2" "$args3" "$args4" "$args5" "$args6" "$args7" ;; 153 | (9) set -- "$args0" "$args1" "$args2" "$args3" "$args4" "$args5" "$args6" "$args7" "$args8" ;; 154 | esac 155 | fi 156 | 157 | # Escape application args 158 | save () { 159 | for i do printf %s\\n "$i" | sed "s/'/'\\\\''/g;1s/^/'/;\$s/\$/' \\\\/" ; done 160 | echo " " 161 | } 162 | APP_ARGS=$(save "$@") 163 | 164 | # Collect all arguments for the java command, following the shell quoting and substitution rules 165 | eval set -- $DEFAULT_JVM_OPTS $JAVA_OPTS $GRADLE_OPTS "\"-Dorg.gradle.appname=$APP_BASE_NAME\"" -classpath "\"$CLASSPATH\"" org.gradle.wrapper.GradleWrapperMain "$APP_ARGS" 166 | 167 | # by default we should be in the correct project dir, but when run from Finder on Mac, the cwd is wrong 168 | if [ "$(uname)" = "Darwin" ] && [ "$HOME" = "$PWD" ]; then 169 | cd "$(dirname "$0")" 170 | fi 171 | 172 | exec "$JAVACMD" "$@" 173 | -------------------------------------------------------------------------------- /gradlew.bat: -------------------------------------------------------------------------------- 1 | @if "%DEBUG%" == "" @echo off 2 | @rem ########################################################################## 3 | @rem 4 | @rem Gradle startup script for Windows 5 | @rem 6 | @rem ########################################################################## 7 | 8 | @rem Set local scope for the variables with windows NT shell 9 | if "%OS%"=="Windows_NT" setlocal 10 | 11 | set DIRNAME=%~dp0 12 | if "%DIRNAME%" == "" set DIRNAME=. 13 | set APP_BASE_NAME=%~n0 14 | set APP_HOME=%DIRNAME% 15 | 16 | @rem Add default JVM options here. You can also use JAVA_OPTS and GRADLE_OPTS to pass JVM options to this script. 17 | set DEFAULT_JVM_OPTS= 18 | 19 | @rem Find java.exe 20 | if defined JAVA_HOME goto findJavaFromJavaHome 21 | 22 | set JAVA_EXE=java.exe 23 | %JAVA_EXE% -version >NUL 2>&1 24 | if "%ERRORLEVEL%" == "0" goto init 25 | 26 | echo. 27 | echo ERROR: JAVA_HOME is not set and no 'java' command could be found in your PATH. 28 | echo. 29 | echo Please set the JAVA_HOME variable in your environment to match the 30 | echo location of your Java installation. 31 | 32 | goto fail 33 | 34 | :findJavaFromJavaHome 35 | set JAVA_HOME=%JAVA_HOME:"=% 36 | set JAVA_EXE=%JAVA_HOME%/bin/java.exe 37 | 38 | if exist "%JAVA_EXE%" goto init 39 | 40 | echo. 41 | echo ERROR: JAVA_HOME is set to an invalid directory: %JAVA_HOME% 42 | echo. 43 | echo Please set the JAVA_HOME variable in your environment to match the 44 | echo location of your Java installation. 45 | 46 | goto fail 47 | 48 | :init 49 | @rem Get command-line arguments, handling Windows variants 50 | 51 | if not "%OS%" == "Windows_NT" goto win9xME_args 52 | 53 | :win9xME_args 54 | @rem Slurp the command line arguments. 55 | set CMD_LINE_ARGS= 56 | set _SKIP=2 57 | 58 | :win9xME_args_slurp 59 | if "x%~1" == "x" goto execute 60 | 61 | set CMD_LINE_ARGS=%* 62 | 63 | :execute 64 | @rem Setup the command line 65 | 66 | set CLASSPATH=%APP_HOME%\gradle\wrapper\gradle-wrapper.jar 67 | 68 | @rem Execute Gradle 69 | "%JAVA_EXE%" %DEFAULT_JVM_OPTS% %JAVA_OPTS% %GRADLE_OPTS% "-Dorg.gradle.appname=%APP_BASE_NAME%" -classpath "%CLASSPATH%" org.gradle.wrapper.GradleWrapperMain %CMD_LINE_ARGS% 70 | 71 | :end 72 | @rem End local scope for the variables with windows NT shell 73 | if "%ERRORLEVEL%"=="0" goto mainEnd 74 | 75 | :fail 76 | rem Set variable GRADLE_EXIT_CONSOLE if you need the _script_ return code instead of 77 | rem the _cmd.exe /c_ return code! 78 | if not "" == "%GRADLE_EXIT_CONSOLE%" exit 1 79 | exit /b 1 80 | 81 | :mainEnd 82 | if "%OS%"=="Windows_NT" endlocal 83 | 84 | :omega 85 | -------------------------------------------------------------------------------- /instructor/advanced/org/jetbrains/kotlinworkshop/advanced/_10Asynchronous/10_Timeout.kt: -------------------------------------------------------------------------------- 1 | package org.jetbrains.kotlinworkshop.advanced._10Asynchronous 2 | 3 | import kotlinx.coroutines.delay 4 | import kotlinx.coroutines.runBlocking 5 | import kotlinx.coroutines.withTimeout 6 | 7 | 8 | fun main() = runBlocking { 9 | withTimeout(3000) { 10 | timeoutProcess() 11 | } 12 | } 13 | 14 | suspend fun timeoutProcess() { 15 | delay(5000) 16 | println("timeoutProcess called") 17 | } 18 | -------------------------------------------------------------------------------- /instructor/advanced/org/jetbrains/kotlinworkshop/advanced/_10Asynchronous/11_Sequential.kt: -------------------------------------------------------------------------------- 1 | package org.jetbrains.kotlinworkshop.advanced._10Asynchronous 2 | 3 | import kotlinx.coroutines.delay 4 | import kotlinx.coroutines.runBlocking 5 | import kotlin.system.measureTimeMillis 6 | 7 | 8 | fun main() = runBlocking { 9 | 10 | val time = measureTimeMillis { 11 | val one = function1() 12 | val two = function2() 13 | println("Result is ${one + two}") 14 | } 15 | println("Total time: $time") 16 | 17 | } 18 | 19 | 20 | suspend fun function1(): Int { 21 | delay(1000) 22 | return 15 23 | } 24 | 25 | suspend fun function2(): Int { 26 | delay(1000) 27 | return 27 28 | } -------------------------------------------------------------------------------- /instructor/advanced/org/jetbrains/kotlinworkshop/advanced/_10Asynchronous/12_Concurrent.kt: -------------------------------------------------------------------------------- 1 | package org.jetbrains.kotlinworkshop.advanced._10Asynchronous 2 | 3 | import kotlinx.coroutines.Dispatchers 4 | import kotlinx.coroutines.async 5 | import kotlinx.coroutines.runBlocking 6 | import kotlin.system.measureTimeMillis 7 | 8 | 9 | fun main() = runBlocking { 10 | 11 | val time = measureTimeMillis { 12 | val one = async(Dispatchers.Default) { function1() } 13 | val two = async(Dispatchers.Default) { function2() } 14 | println("Result is ${one.await() + two.await()}") 15 | } 16 | println("Total time: $time") 17 | 18 | } 19 | 20 | 21 | -------------------------------------------------------------------------------- /instructor/advanced/org/jetbrains/kotlinworkshop/advanced/_10Asynchronous/13_Lazy.kt: -------------------------------------------------------------------------------- 1 | package org.jetbrains.kotlinworkshop.advanced._10Asynchronous 2 | 3 | import kotlinx.coroutines.CoroutineStart 4 | import kotlinx.coroutines.Dispatchers 5 | import kotlinx.coroutines.async 6 | import kotlinx.coroutines.runBlocking 7 | import kotlin.system.measureTimeMillis 8 | 9 | 10 | fun main() = runBlocking { 11 | 12 | val time = measureTimeMillis { 13 | val one = async(Dispatchers.Default, CoroutineStart.LAZY) { function1() } 14 | val two = async(Dispatchers.Default, CoroutineStart.LAZY) { function2() } 15 | println("Result is ${one.await() + two.await()}") 16 | } 17 | println("Total time: $time") 18 | 19 | } 20 | 21 | 22 | -------------------------------------------------------------------------------- /instructor/advanced/org/jetbrains/kotlinworkshop/advanced/_10Asynchronous/14_Dispatchers.kt: -------------------------------------------------------------------------------- 1 | package org.jetbrains.kotlinworkshop.advanced._10Asynchronous 2 | 3 | import kotlinx.coroutines.* 4 | 5 | 6 | fun main() = runBlocking { 7 | 8 | val jobs = arrayListOf() 9 | 10 | jobs += launch(Dispatchers.Unconfined) { 11 | println("Unconfined: ${threadName()}") 12 | } 13 | 14 | jobs += launch() { 15 | isActive 16 | println("CommonPool: ${threadName()}") 17 | } 18 | 19 | jobs += launch(newSingleThreadContext("CustomThread")) { 20 | println("CustomThread: ${threadName()}") 21 | } 22 | 23 | /*jobs += launch(coroutineContext) { 24 | println("CustomThread: ${threadName()}") 25 | }*/ 26 | 27 | } 28 | 29 | 30 | 31 | 32 | fun threadName(): String = Thread.currentThread().name -------------------------------------------------------------------------------- /instructor/advanced/org/jetbrains/kotlinworkshop/advanced/_10Asynchronous/15_Channels.kt: -------------------------------------------------------------------------------- 1 | package org.jetbrains.kotlinworkshop.advanced._10Asynchronous 2 | 3 | import kotlinx.coroutines.channels.Channel 4 | import kotlinx.coroutines.launch 5 | import kotlinx.coroutines.runBlocking 6 | 7 | 8 | fun main() = runBlocking { 9 | val channel = Channel() 10 | 11 | launch { 12 | for (x in 1..5) { 13 | channel.send(x * x) 14 | } 15 | } 16 | repeat(5) { 17 | println(channel.receive()) 18 | } 19 | } 20 | 21 | -------------------------------------------------------------------------------- /instructor/advanced/org/jetbrains/kotlinworkshop/advanced/_10Asynchronous/16_ClosingChannels.kt: -------------------------------------------------------------------------------- 1 | package org.jetbrains.kotlinworkshop.advanced._10Asynchronous 2 | 3 | import kotlinx.coroutines.channels.Channel 4 | import kotlinx.coroutines.launch 5 | import kotlinx.coroutines.runBlocking 6 | 7 | 8 | fun main() = runBlocking { 9 | val channel = Channel() 10 | 11 | launch { 12 | for (x in 1..7) { 13 | channel.send(x * x) 14 | } 15 | channel.close() 16 | } 17 | for (y in channel) { 18 | println(channel.receive()) 19 | } 20 | } 21 | 22 | -------------------------------------------------------------------------------- /instructor/advanced/org/jetbrains/kotlinworkshop/advanced/_10Asynchronous/17_ProduceConsume.kt: -------------------------------------------------------------------------------- 1 | package org.jetbrains.kotlinworkshop.advanced._10Asynchronous 2 | 3 | import kotlinx.coroutines.CoroutineScope 4 | import kotlinx.coroutines.channels.consumeEach 5 | import kotlinx.coroutines.channels.produce 6 | import kotlinx.coroutines.runBlocking 7 | 8 | 9 | fun main() = runBlocking { 10 | val squares = produceSquares() 11 | squares.consumeEach { 12 | println(it) 13 | } 14 | } 15 | 16 | 17 | fun CoroutineScope.produceSquares() = produce { 18 | for (x in 1..5) { 19 | send (x * x) 20 | } 21 | } -------------------------------------------------------------------------------- /instructor/advanced/org/jetbrains/kotlinworkshop/advanced/_10Asynchronous/18_Pipeline.kt: -------------------------------------------------------------------------------- 1 | package org.jetbrains.kotlinworkshop.advanced._18_Pipeline 2 | 3 | import kotlinx.coroutines.CoroutineScope 4 | import kotlinx.coroutines.channels.ReceiveChannel 5 | import kotlinx.coroutines.channels.produce 6 | import kotlinx.coroutines.runBlocking 7 | 8 | 9 | fun CoroutineScope.producerPipeline() = produce { 10 | var x = 1 11 | while (true) send(x++) 12 | } 13 | 14 | fun CoroutineScope.consumerPipeline(numbers: ReceiveChannel) = produce { 15 | for (x in numbers) { 16 | send(x * x) 17 | } 18 | } 19 | 20 | fun main() = runBlocking { 21 | val numbers = producerPipeline() 22 | val squares = consumerPipeline(numbers) 23 | for (i in 1..5) { 24 | println(squares.receive()) 25 | } 26 | squares.cancel() 27 | } -------------------------------------------------------------------------------- /instructor/advanced/org/jetbrains/kotlinworkshop/advanced/_10Asynchronous/19_SharedState.kt: -------------------------------------------------------------------------------- 1 | package org.jetbrains.kotlinworkshop.advanced._10Asynchronous 2 | 3 | 4 | import kotlinx.coroutines.* 5 | import java.util.concurrent.Executors 6 | import kotlin.coroutines.CoroutineContext 7 | import kotlin.system.measureTimeMillis 8 | 9 | 10 | val counterContext = Executors.newSingleThreadExecutor().asCoroutineDispatcher() 11 | 12 | var counter = 0 13 | 14 | fun main() = runBlocking { 15 | // Switch to counterContext for faster execution 16 | massiveRun(Dispatchers.Default) { 17 | withContext(counterContext) { // remove run when switching to counterContext 18 | counter++ 19 | } 20 | } 21 | println("Counter = ${counter}") 22 | } 23 | 24 | suspend fun massiveRun(context: CoroutineContext, action: suspend () -> Unit) { 25 | val n = 1000 26 | val k = 1000 27 | val time = measureTimeMillis { 28 | val jobs = List(n) { 29 | GlobalScope.launch(context) { 30 | repeat(k) { action() } 31 | } 32 | } 33 | jobs.forEach { it.join() } 34 | } 35 | println("Completed ${ n * k} actions in $time ms") 36 | 37 | } -------------------------------------------------------------------------------- /instructor/advanced/org/jetbrains/kotlinworkshop/advanced/_10Asynchronous/1_LongRunningProcess.kt: -------------------------------------------------------------------------------- 1 | package org.jetbrains.kotlinworkshop.advanced._10Asynchronous 2 | 3 | 4 | fun main() { 5 | 6 | 7 | println("Starting here") 8 | longRunningProcess() 9 | println("Ending here") 10 | 11 | } 12 | 13 | fun longRunningProcess() { 14 | Thread.sleep(5000) 15 | println("in process") 16 | } 17 | -------------------------------------------------------------------------------- /instructor/advanced/org/jetbrains/kotlinworkshop/advanced/_10Asynchronous/20_Actors.kt: -------------------------------------------------------------------------------- 1 | package com.hadihariri.kotlin.async 2 | 3 | 4 | import kotlinx.coroutines.CompletableDeferred 5 | import kotlinx.coroutines.CoroutineScope 6 | import kotlinx.coroutines.Dispatchers 7 | import kotlinx.coroutines.channels.actor 8 | import kotlinx.coroutines.runBlocking 9 | import org.jetbrains.kotlinworkshop.advanced._10Asynchronous.massiveRun 10 | 11 | 12 | sealed class CounterMessage 13 | object IncCounter: CounterMessage() 14 | class GetCounter(val response: CompletableDeferred): CounterMessage() 15 | 16 | fun CoroutineScope.counterActor() = actor { 17 | var counter = 0 18 | for (msg in channel) { 19 | when (msg) { 20 | is IncCounter -> counter++ 21 | is GetCounter -> msg.response.complete(counter) 22 | } 23 | } 24 | } 25 | 26 | fun main() = runBlocking { 27 | val counter = counterActor() 28 | massiveRun(Dispatchers.Default) { 29 | counter.send(IncCounter) 30 | } 31 | val response = CompletableDeferred() 32 | counter.send(GetCounter(response)) 33 | println("Counter = ${response.await()}") 34 | counter.close() 35 | } -------------------------------------------------------------------------------- /instructor/advanced/org/jetbrains/kotlinworkshop/advanced/_10Asynchronous/2_SuspendableComputation.kt: -------------------------------------------------------------------------------- 1 | package org.jetbrains.kotlinworkshop.advanced._10Asynchronous 2 | 3 | import kotlinx.coroutines.launch 4 | import kotlinx.coroutines.runBlocking 5 | 6 | fun main() = runBlocking { 7 | 8 | 9 | println("Starting here") 10 | launch { 11 | suspendableProcess() 12 | } 13 | println("Ending here") 14 | 15 | } 16 | 17 | suspend fun suspendableProcess() { 18 | Thread.sleep(2000) 19 | println("in process") 20 | } 21 | -------------------------------------------------------------------------------- /instructor/advanced/org/jetbrains/kotlinworkshop/advanced/_10Asynchronous/3_SuspendableComputationLoop.kt: -------------------------------------------------------------------------------- 1 | package org.jetbrains.kotlinworkshop.advanced._10Asynchronous 2 | 3 | import kotlinx.coroutines.launch 4 | import kotlinx.coroutines.runBlocking 5 | 6 | 7 | fun main() = runBlocking { 8 | 9 | 10 | println("Starting here") 11 | launch { 12 | 13 | suspendableProcess() 14 | } 15 | println("Ending here") 16 | while (true) {} 17 | } 18 | -------------------------------------------------------------------------------- /instructor/advanced/org/jetbrains/kotlinworkshop/advanced/_10Asynchronous/4_SuspendableComputationSleep.kt: -------------------------------------------------------------------------------- 1 | package org.jetbrains.kotlinworkshop.advanced._10Asynchronous 2 | 3 | import kotlinx.coroutines.launch 4 | import kotlinx.coroutines.runBlocking 5 | 6 | fun main() = runBlocking { 7 | println("Starting here") 8 | launch() { 9 | suspendableProcess() 10 | } 11 | println("Ending here") 12 | Thread.sleep(4000) 13 | } 14 | -------------------------------------------------------------------------------- /instructor/advanced/org/jetbrains/kotlinworkshop/advanced/_10Asynchronous/5_SuspendableComputationDelay.kt: -------------------------------------------------------------------------------- 1 | package org.jetbrains.kotlinworkshop.advanced._10Asynchronous 2 | 3 | import kotlinx.coroutines.delay 4 | import kotlinx.coroutines.launch 5 | import kotlinx.coroutines.runBlocking 6 | 7 | 8 | fun main() = runBlocking { 9 | println("Starting here") 10 | launch { 11 | suspendableProcess() 12 | } 13 | println("Ending here") 14 | delay(4000) 15 | } 16 | -------------------------------------------------------------------------------- /instructor/advanced/org/jetbrains/kotlinworkshop/advanced/_10Asynchronous/6A_Comparison.kt: -------------------------------------------------------------------------------- 1 | package org.jetbrains.kotlinworkshop.advanced._10Asynchronous 2 | 3 | import kotlinx.coroutines.GlobalScope 4 | import kotlinx.coroutines.delay 5 | import kotlinx.coroutines.launch 6 | import kotlinx.coroutines.runBlocking 7 | import kotlin.concurrent.thread 8 | 9 | 10 | fun threads() { 11 | val jobs = 1..100000 12 | jobs.forEach { 13 | 14 | thread { 15 | Thread.sleep(1000L) 16 | print(".") 17 | } 18 | } 19 | } 20 | 21 | 22 | fun coroutines() = runBlocking { 23 | val jobs = List(100000) { 24 | GlobalScope.launch() { 25 | delay(1000L) 26 | print(".") 27 | } 28 | } 29 | jobs.forEach { it.join() } 30 | } 31 | 32 | 33 | 34 | fun main() { 35 | 36 | coroutines() 37 | // threads() 38 | 39 | } -------------------------------------------------------------------------------- /instructor/advanced/org/jetbrains/kotlinworkshop/advanced/_10Asynchronous/6_SuspendableComputationJoin.kt: -------------------------------------------------------------------------------- 1 | package org.jetbrains.kotlinworkshop.advanced._10Asynchronous 2 | 3 | import kotlinx.coroutines.launch 4 | import kotlinx.coroutines.runBlocking 5 | 6 | fun main() = runBlocking { 7 | println("Starting here") 8 | val job = launch() { 9 | suspendableProcess() 10 | } 11 | println("Ending here") 12 | job.join() 13 | } 14 | 15 | -------------------------------------------------------------------------------- /instructor/advanced/org/jetbrains/kotlinworkshop/advanced/_10Asynchronous/7_WorkingWithJobs.kt: -------------------------------------------------------------------------------- 1 | package org.jetbrains.kotlinworkshop.advanced._10Asynchronous 2 | 3 | import kotlinx.coroutines.delay 4 | import kotlinx.coroutines.launch 5 | import kotlinx.coroutines.runBlocking 6 | 7 | 8 | fun main() = runBlocking { 9 | val job = launch { 10 | longRunning() 11 | } 12 | delay(4000) 13 | job.cancel() 14 | } 15 | 16 | suspend fun longRunning() { 17 | delay(10000) 18 | println("longRunning called") 19 | } 20 | -------------------------------------------------------------------------------- /instructor/advanced/org/jetbrains/kotlinworkshop/advanced/_10Asynchronous/8_NonCancellable.kt: -------------------------------------------------------------------------------- 1 | package org.jetbrains.kotlinworkshop.advanced._10Asynchronous 2 | 3 | import kotlinx.coroutines.delay 4 | import kotlinx.coroutines.launch 5 | import kotlinx.coroutines.runBlocking 6 | 7 | 8 | fun main() = runBlocking { 9 | val job = launch { 10 | var nextPrintTime = System.currentTimeMillis() 11 | var i = 0 12 | while (true) { // computation loop 13 | val currentTime = System.currentTimeMillis() 14 | if (currentTime >= nextPrintTime) { 15 | println("I'm sleeping ${i++} ...") 16 | nextPrintTime += 500L 17 | } 18 | } } 19 | delay(1300L) // delay a bit 20 | println("main: I'm tired of waiting!") 21 | job.cancel() // cancels the job 22 | delay(1300L) // delay a bit to see if it was cancelled.... 23 | println("main: Now I can quit.") 24 | } 25 | -------------------------------------------------------------------------------- /instructor/advanced/org/jetbrains/kotlinworkshop/advanced/_10Asynchronous/9_Cancellable.kt: -------------------------------------------------------------------------------- 1 | package org.jetbrains.kotlinworkshop.advanced._10Asynchronous 2 | 3 | import kotlinx.coroutines.delay 4 | import kotlinx.coroutines.isActive 5 | import kotlinx.coroutines.launch 6 | import kotlinx.coroutines.runBlocking 7 | 8 | 9 | fun main() = runBlocking { 10 | val job = launch { 11 | var nextPrintTime = System.currentTimeMillis() 12 | var i = 0 13 | while (isActive) { // computation loop 14 | val currentTime = System.currentTimeMillis() 15 | if (currentTime >= nextPrintTime) { 16 | println("I'm sleeping ${i++} ...") 17 | nextPrintTime += 500L 18 | } 19 | } } 20 | delay(1300L) // delay a bit 21 | println("main: I'm tired of waiting!") 22 | job.cancel() // cancels the job 23 | delay(1300L) // delay a bit to see if it was cancelled.... 24 | println("main: Now I can quit.") 25 | } 26 | -------------------------------------------------------------------------------- /instructor/advanced/org/jetbrains/kotlinworkshop/advanced/_1Object/_1Object.kt: -------------------------------------------------------------------------------- 1 | package org.jetbrains.kotlinworkshop.advanced._1Object 2 | 3 | object KSingleton { 4 | fun foo() {} 5 | } 6 | 7 | fun main() { 8 | KSingleton.foo() 9 | } -------------------------------------------------------------------------------- /instructor/advanced/org/jetbrains/kotlinworkshop/advanced/_1Object/_2CompanionObject.kt: -------------------------------------------------------------------------------- 1 | package org.jetbrains.kotlinworkshop.advanced._1Object 2 | 3 | interface Factory { 4 | fun create(): T 5 | } 6 | 7 | // Companion object can implement an interface 8 | class A { 9 | private constructor() 10 | 11 | companion object : Factory { 12 | override fun create(): A { 13 | return A() 14 | } 15 | 16 | // to make it static use annotation 17 | @JvmStatic 18 | fun staticFunction() { 19 | } 20 | } 21 | } -------------------------------------------------------------------------------- /instructor/advanced/org/jetbrains/kotlinworkshop/advanced/_1Object/_3JSingleton.java: -------------------------------------------------------------------------------- 1 | package org.jetbrains.kotlinworkshop.advanced._1Object; 2 | 3 | public class _3JSingleton { 4 | public final static _3JSingleton INSTANCE = new _3JSingleton(); 5 | 6 | private _3JSingleton() { 7 | } 8 | 9 | public void foo() { 10 | } 11 | } 12 | -------------------------------------------------------------------------------- /instructor/advanced/org/jetbrains/kotlinworkshop/advanced/_1Object/_4UsingCompanionObjectFromJava.java: -------------------------------------------------------------------------------- 1 | package org.jetbrains.kotlinworkshop.advanced._1Object; 2 | 3 | public class _4UsingCompanionObjectFromJava { 4 | 5 | public static void main(String[] args) { 6 | 7 | A.Companion.create(); 8 | // A.create() //- doesn't compile 9 | 10 | A.Companion.staticFunction(); 11 | A.staticFunction(); 12 | } 13 | } 14 | -------------------------------------------------------------------------------- /instructor/advanced/org/jetbrains/kotlinworkshop/advanced/_1Object/_5UsingKotlinObjectFromJava.java: -------------------------------------------------------------------------------- 1 | package org.jetbrains.kotlinworkshop.advanced._1Object; 2 | 3 | public class _5UsingKotlinObjectFromJava { 4 | public static void main(String[] args) { 5 | _3JSingleton.INSTANCE.foo(); 6 | KSingleton.INSTANCE.foo(); 7 | } 8 | } 9 | -------------------------------------------------------------------------------- /instructor/advanced/org/jetbrains/kotlinworkshop/advanced/_2Interop/Session.java: -------------------------------------------------------------------------------- 1 | package org.jetbrains.kotlinworkshop.advanced._2Interop; 2 | 3 | public class Session { 4 | public String getDescription() { 5 | return null; 6 | } 7 | } 8 | -------------------------------------------------------------------------------- /instructor/advanced/org/jetbrains/kotlinworkshop/advanced/_2Interop/UsingEmployee.java: -------------------------------------------------------------------------------- 1 | package org.jetbrains.kotlinworkshop.advanced._2Interop; 2 | 3 | public class UsingEmployee { 4 | 5 | public static void main(String[] args) { 6 | 7 | Employee employee = new Employee(); 8 | 9 | employee.getField(); 10 | employee.setField("Value"); 11 | 12 | 13 | } 14 | } 15 | -------------------------------------------------------------------------------- /instructor/advanced/org/jetbrains/kotlinworkshop/advanced/_2Interop/UsingThrow.java: -------------------------------------------------------------------------------- 1 | package org.jetbrains.kotlinworkshop.advanced._2Interop; 2 | 3 | public class UsingThrow { 4 | 5 | 6 | public void usingThrow() { 7 | _4ThrowsKt.throwsException("Something"); 8 | } 9 | } 10 | -------------------------------------------------------------------------------- /instructor/advanced/org/jetbrains/kotlinworkshop/advanced/_2Interop/_1PlatformTypes.kt: -------------------------------------------------------------------------------- 1 | package org.jetbrains.kotlinworkshop.advanced._2Interop 2 | 3 | fun main() { 4 | explicitNullableType() 5 | explicitNotNullType() 6 | noExplicitType() 7 | } 8 | 9 | fun noExplicitType() { 10 | val session = Session() 11 | val description = session.description 12 | println(description.length) // NPE 13 | } 14 | 15 | fun explicitNotNullType() { 16 | val session = Session() 17 | val description: String = session.description // IllegalStateException 18 | println(description.length) 19 | 20 | } 21 | 22 | fun explicitNullableType() { 23 | val session = Session() 24 | val description: String? = session.description // ok 25 | println(description?.length) // null 26 | } -------------------------------------------------------------------------------- /instructor/advanced/org/jetbrains/kotlinworkshop/advanced/_2Interop/_2ExtensionsFromJava.java: -------------------------------------------------------------------------------- 1 | package org.jetbrains.kotlinworkshop.advanced._2Interop; 2 | 3 | 4 | import static org.jetbrains.kotlinworkshop.advanced._8Dsl._1ExtensionWithInfixKt.toTitleCase; 5 | 6 | public class _2ExtensionsFromJava { 7 | public static void main(String[] args) { 8 | String sample = "to title case"; 9 | 10 | toTitleCase("sample"); 11 | } 12 | } 13 | -------------------------------------------------------------------------------- /instructor/advanced/org/jetbrains/kotlinworkshop/advanced/_2Interop/_3InteropAnnotations.kt: -------------------------------------------------------------------------------- 1 | @file:JvmName("Foo") 2 | 3 | package org.jetbrains.kotlinworkshop.advanced._2Interop 4 | 5 | 6 | class Employee { 7 | // @JvmField will make this a field and eliminate property accessors 8 | var field = "" 9 | } 10 | 11 | fun process(input: List) { 12 | 13 | } 14 | 15 | @JvmName("processStrings") 16 | fun process(input: List) { 17 | 18 | } 19 | 20 | 21 | // Others: @JvmStatic, @JvmOverload, etc. See https://kotlinlang.org/api/latest/jvm/stdlib/kotlin.jvm/index.html -------------------------------------------------------------------------------- /instructor/advanced/org/jetbrains/kotlinworkshop/advanced/_2Interop/_4Throws.kt: -------------------------------------------------------------------------------- 1 | package org.jetbrains.kotlinworkshop.advanced._2Interop 2 | 3 | import java.io.* 4 | 5 | //@Throws(IOException::class) 6 | fun throwsException(value: String) { 7 | throw IOException("Java needs to know this") 8 | } -------------------------------------------------------------------------------- /instructor/advanced/org/jetbrains/kotlinworkshop/advanced/_3InlineFunctions/_1RunFunction.kt: -------------------------------------------------------------------------------- 1 | package org.jetbrains.kotlinworkshop.advanced._3InlineFunctions 2 | 3 | val foo = run { 4 | println("Calculating foo...") 5 | "foo" 6 | } 7 | 8 | fun main() { 9 | println(foo) 10 | } -------------------------------------------------------------------------------- /instructor/advanced/org/jetbrains/kotlinworkshop/advanced/_3InlineFunctions/_2LetFunction.kt: -------------------------------------------------------------------------------- 1 | package org.jetbrains.kotlinworkshop.advanced._3InlineFunctions 2 | 3 | fun sendEmailTo(email: String) { 4 | /*...*/ 5 | } 6 | 7 | fun example(email: String?) { 8 | 9 | if (email != null) sendEmailTo(email) 10 | email?.let { e -> sendEmailTo(e) } 11 | 12 | val e = getEmail() 13 | if (e != null) sendEmailTo(e) 14 | 15 | getEmail()?.let { sendEmailTo(it) } 16 | } 17 | 18 | inline fun T.let(block: (T) -> R): R = block(this) 19 | 20 | fun getEmail(): String? = null -------------------------------------------------------------------------------- /instructor/advanced/org/jetbrains/kotlinworkshop/advanced/_3InlineFunctions/_3SynchronizedFunction.kt: -------------------------------------------------------------------------------- 1 | package org.jetbrains.kotlinworkshop.advanced._3InlineFunctions 2 | 3 | import java.util.concurrent.locks.* 4 | import kotlin.concurrent.* 5 | 6 | inline fun synchronized(lock: Lock, action: () -> T): T { 7 | lock.lock() 8 | try { 9 | return action() 10 | } finally { 11 | lock.unlock() 12 | } 13 | } 14 | 15 | fun main() { 16 | 17 | val l = ReentrantLock() 18 | 19 | synchronized(l) { 20 | // ... 21 | } 22 | 23 | l.withLock { 24 | // ... 25 | } 26 | } -------------------------------------------------------------------------------- /instructor/advanced/org/jetbrains/kotlinworkshop/advanced/_3InlineFunctions/_4TakeIfAndTakeUnlessFunctions.kt: -------------------------------------------------------------------------------- 1 | package org.jetbrains.kotlinworkshop.advanced._3InlineFunctions 2 | 3 | data class Contract(val info: String, val isSigned: Boolean) 4 | 5 | fun main() { 6 | val contract1 = Contract("Kotlin training", true) 7 | println(contract1.takeIf { it.isSigned }) // contract1 8 | 9 | val contract2 = Contract("Other training", false) 10 | println(contract2.takeIf { it.isSigned }) // null 11 | 12 | val number = 42 13 | println(number.takeIf { it > 10 }) // 42 14 | 15 | val other = 2 16 | println(other.takeIf { it > 10 }) // null 17 | 18 | println(contract1.takeUnless { it.isSigned }) // null 19 | 20 | println(contract2.takeUnless { it.isSigned }) // contract2 21 | 22 | println(number.takeUnless { it > 10 }) // null 23 | 24 | println(other.takeUnless { it > 10 }) // 2 25 | } -------------------------------------------------------------------------------- /instructor/advanced/org/jetbrains/kotlinworkshop/advanced/_3InlineFunctions/_5RepeatFunction.kt: -------------------------------------------------------------------------------- 1 | package org.jetbrains.kotlinworkshop.advanced._3InlineFunctions 2 | 3 | fun main() { 4 | repeat(10) { 5 | println("Welcome!") 6 | } 7 | } -------------------------------------------------------------------------------- /instructor/advanced/org/jetbrains/kotlinworkshop/advanced/_3InlineFunctions/_6NoInline.kt: -------------------------------------------------------------------------------- 1 | package org.jetbrains.kotlinworkshop.advanced._3InlineFunctions 2 | 3 | 4 | // adding inline below changes things 5 | // add params noinline 6 | inline fun operation(x: Int, y: Int, noinline func: (Int, Int) -> Int) { 7 | println("Function being called") 8 | func(x, y) 9 | println("Function was called") 10 | 11 | } -------------------------------------------------------------------------------- /instructor/advanced/org/jetbrains/kotlinworkshop/advanced/_4Returns/_1NonLocalReturns.kt: -------------------------------------------------------------------------------- 1 | package org.jetbrains.kotlinworkshop.advanced._4Returns 2 | 3 | 4 | fun main() { 5 | containingFunction() 6 | 7 | } 8 | 9 | // non-local returns 10 | fun containingFunction() { 11 | val numbers = 1..100 12 | numbers.forEach { 13 | if (it % 5 == 0) return 14 | } 15 | println("Hello") 16 | } 17 | 18 | inline fun Iterable.myForEach(f: (T) -> Unit) { 19 | for (element in this) f(element) 20 | } 21 | 22 | fun containingFunction2() { 23 | val numbers = 1..100 24 | numbers.myForEach { 25 | if (it % 5 == 0) return 26 | } 27 | println("Hello") 28 | } 29 | 30 | 31 | -------------------------------------------------------------------------------- /instructor/advanced/org/jetbrains/kotlinworkshop/advanced/_4Returns/_2LocalReturns.kt: -------------------------------------------------------------------------------- 1 | package org.jetbrains.kotlinworkshop.advanced._4Returns 2 | 3 | fun main() { 4 | 5 | } 6 | 7 | fun containingFunction3() { 8 | val numbers = 1..100 9 | numbers.forEach { 10 | if (it % 5 == 0) return@forEach 11 | } 12 | println("Hello") 13 | } 14 | 15 | fun containingFunction4() { 16 | val numbers = 1..100 17 | numbers.forEach myLabel@ { 18 | if (it % 5 == 0) return@myLabel 19 | } 20 | } 21 | 22 | fun containingFunction5() { 23 | val numbers = 1..100 24 | numbers.forEach(fun(element) { 25 | if (element % 5 == 0) return 26 | }) 27 | println("Hello") 28 | } 29 | 30 | 31 | 32 | 33 | -------------------------------------------------------------------------------- /instructor/advanced/org/jetbrains/kotlinworkshop/advanced/_4Returns/_3Nothing.kt: -------------------------------------------------------------------------------- 1 | package org.jetbrains.kotlinworkshop.advanced._4Returns 2 | 3 | // Add Nothing 4 | fun endlessLoop() { 5 | 6 | while (true) { 7 | // do something 8 | } 9 | 10 | } 11 | 12 | 13 | fun main() { 14 | 15 | 16 | endlessLoop() 17 | println("Never will reach here") 18 | } -------------------------------------------------------------------------------- /instructor/advanced/org/jetbrains/kotlinworkshop/advanced/_5Reified/_1TypeErasure.kt: -------------------------------------------------------------------------------- 1 | package org.jetbrains.kotlinworkshop.advanced._5Reified 2 | 3 | // Erasure of Generic Types 4 | 5 | // Erasure of Generic Methods 6 | 7 | class Node(val data: T, val next: Node) 8 | 9 | /* 10 | public final class Node { 11 | 12 | private final Ljava/lang/Object; data 13 | 14 | public final getData()Ljava/lang/Object; 15 | 16 | private final LNode; next 17 | 18 | public final getNext()LNode; 19 | 20 | public (Ljava/lang/Object;LNode;)V 21 | } 22 | 23 | */ 24 | 25 | fun foo(t: T) {} 26 | fun > bar(t: T) {} 27 | 28 | /* 29 | public final static foo(Ljava/lang/Object;)V 30 | 31 | public final static bar(Ljava/lang/Comparable;)V 32 | */ 33 | -------------------------------------------------------------------------------- /instructor/advanced/org/jetbrains/kotlinworkshop/advanced/_5Reified/_2Reified.kt: -------------------------------------------------------------------------------- 1 | package org.jetbrains.kotlinworkshop.advanced._5Reified 2 | 3 | inline fun isA(value: Any) = value is T 4 | 5 | fun main() { 6 | println(isA("abc")) 7 | println(isA(123)) 8 | } -------------------------------------------------------------------------------- /instructor/advanced/org/jetbrains/kotlinworkshop/advanced/_5Reified/_3FilterIsInstance.kt: -------------------------------------------------------------------------------- 1 | package org.jetbrains.kotlinworkshop.advanced._5Reified 2 | 3 | fun main() { 4 | val anys: List = 5 | listOf(1, "one", 2.0) 6 | 7 | val strings: List = 8 | anys. 9 | filterIsInstance() 10 | /* 11 | The code generated by the compiler 12 | instead of calling inline function 'filterIsInstance': 13 | 14 | val destination = mutableListOf() 15 | for (element in this) { 16 | if (element is String) { 17 | destination.add(element) 18 | } 19 | } 20 | val strings = destination 21 | */ 22 | 23 | println(strings) 24 | } 25 | 26 | inline fun 27 | Iterable<*>.filterIsInstance(): List { 28 | 29 | val destination = mutableListOf() 30 | for (element in this) { 31 | if (element is T) { 32 | destination.add(element) 33 | } 34 | } 35 | return destination 36 | } -------------------------------------------------------------------------------- /instructor/advanced/org/jetbrains/kotlinworkshop/advanced/_5Reified/_4ClassReferences.kt: -------------------------------------------------------------------------------- 1 | package org.jetbrains.kotlinworkshop.advanced._5Reified 2 | 3 | import java.util.* 4 | 5 | class Service 6 | 7 | fun main() { 8 | 9 | ServiceLoader.load(Service::class.java) 10 | 11 | loadService() 12 | } 13 | 14 | inline fun loadService() = 15 | ServiceLoader.load(T::class.java) 16 | -------------------------------------------------------------------------------- /instructor/advanced/org/jetbrains/kotlinworkshop/advanced/_5Reified/_5Validators.kt: -------------------------------------------------------------------------------- 1 | package org.jetbrains.kotlinworkshop.advanced._5Reified 2 | 3 | import kotlin.reflect.* 4 | 5 | interface FieldValidator { 6 | fun validate(input: T): Boolean 7 | } 8 | 9 | object Validators { 10 | private val validators = mutableMapOf, FieldValidator<*>>() 11 | 12 | fun registerValidator( 13 | kClass: KClass, fieldValidator: FieldValidator) { 14 | validators[kClass] = fieldValidator 15 | } 16 | 17 | @Suppress("UNCHECKED_CAST") 18 | operator fun get(kClass: KClass): FieldValidator? = 19 | validators[kClass] as FieldValidator? 20 | } 21 | 22 | 23 | object DefaultStringValidator : FieldValidator { 24 | override fun validate(input: String) = input.isNotEmpty() 25 | } 26 | 27 | object DefaultIntValidator : FieldValidator { 28 | override fun validate(input: Int) = input >= 0 29 | } 30 | 31 | fun main() { 32 | Validators.registerValidator(String::class, DefaultStringValidator) 33 | Validators.registerValidator(Int::class, DefaultIntValidator) 34 | 35 | println(Validators[String::class]?.validate("Kotlin")) 36 | println(Validators[Int::class]?.validate(42)) 37 | } -------------------------------------------------------------------------------- /instructor/advanced/org/jetbrains/kotlinworkshop/advanced/_5Reified/_6RestrictionsOnReifiedTypeParameters.kt: -------------------------------------------------------------------------------- 1 | package org.jetbrains.kotlinworkshop.advanced._5Reified 2 | 3 | // Which of the following calls won't compile? 4 | 5 | //inline fun foo(t: T) { 6 | // bar(t) 7 | //} 8 | 9 | fun bar(t: T) { 10 | // foo(t) 11 | } -------------------------------------------------------------------------------- /instructor/advanced/org/jetbrains/kotlinworkshop/advanced/_6LazyEvaluation/_1AsSequence.kt: -------------------------------------------------------------------------------- 1 | package org.jetbrains.kotlinworkshop.advanced._6LazyEvaluation 2 | 3 | 4 | fun main() { 5 | 6 | 7 | val numbers = 1..100_000_000 8 | 9 | numbers.filter { it % 5 == 0 }.take(30) 10 | 11 | 12 | numbers.asSequence().filter { it % 5 == 0 }.take(30) 13 | 14 | 15 | } -------------------------------------------------------------------------------- /instructor/advanced/org/jetbrains/kotlinworkshop/advanced/_6LazyEvaluation/_2GenerateSequence.kt: -------------------------------------------------------------------------------- 1 | package org.jetbrains.kotlinworkshop.advanced._6LazyEvaluation 2 | 3 | 4 | fun main() { 5 | 6 | 7 | generateSequence(1) { 8 | it * 10 9 | }.take(300).map { it % 5 } 10 | 11 | 12 | } -------------------------------------------------------------------------------- /instructor/advanced/org/jetbrains/kotlinworkshop/advanced/_7FunctionalConstructs/_1AlgebraicDataTypes.kt: -------------------------------------------------------------------------------- 1 | package org.jetbrains.kotlinworkshop.advanced._7FunctionalConstructs 2 | 3 | 4 | sealed class Expr { 5 | class Num(val value: Int) : Expr() 6 | class Sum(val left: Expr, val right: Expr) : Expr() 7 | } 8 | 9 | fun eval(e: Expr): Int = when (e) { 10 | is Expr.Num -> e.value 11 | is Expr.Sum -> eval(e.left) + eval(e.right) 12 | } 13 | 14 | fun main() { 15 | // 1 + (2 + 3) 16 | println(eval(Expr.Sum(Expr.Num(1), Expr.Sum(Expr.Num(2), Expr.Num(3))))) 17 | } 18 | 19 | 20 | sealed class Result 21 | 22 | class Success : Result() 23 | class Failure : Result() 24 | -------------------------------------------------------------------------------- /instructor/advanced/org/jetbrains/kotlinworkshop/advanced/_7FunctionalConstructs/_2Currying.kt: -------------------------------------------------------------------------------- 1 | package org.jetbrains.kotlinworkshop.advanced._7FunctionalConstructs 2 | 3 | 4 | fun Function2.curry(): (P1) -> (P2) -> R { 5 | return { p1: P1 -> { p2: P2 -> this (p1, p2)}} 6 | } 7 | 8 | fun Function3.curry(): (P1) -> (P2) -> (P3) -> R { 9 | return { p1: P1 -> { p2: P2 -> { p3: P3 -> this (p1, p2, p3)}}} 10 | } 11 | 12 | fun main() { 13 | 14 | val sum = { x: Int, y: Int, z: Int -> x + y + z } 15 | 16 | val sumCurried = sum.curry() 17 | 18 | val result = sumCurried(3)(2)(5) 19 | 20 | println(result) 21 | } 22 | 23 | -------------------------------------------------------------------------------- /instructor/advanced/org/jetbrains/kotlinworkshop/advanced/_7FunctionalConstructs/_3Partials.kt: -------------------------------------------------------------------------------- 1 | package org.jetbrains.kotlinworkshop.advanced._7FunctionalConstructs 2 | 3 | 4 | class Partial 5 | 6 | fun partial(): Partial = Partial() 7 | 8 | fun Function2.createPartialFunction(p1: 9 | P1, partial2: Partial = partial()): (P2) -> R { 10 | return { p2: P2 -> this(p1, p2) } 11 | } 12 | 13 | fun Function2.createPartialFunction(partial1: Partial = partial(), 14 | p2: P2): (P1) -> R { 15 | return { p1: P1 -> this(p1, p2) } 16 | } 17 | 18 | 19 | fun Function5.createPartialFunction(partial1: Partial = partial(), 20 | partial2: Partial = partial(), 21 | partial3: Partial = partial(), 22 | partial4: Partial = partial(), 23 | p5: P5): (P1, P2, P3, P4) -> R { 24 | return { p1: P1, p2: P2, p3: P3, p4: P4 -> this(p1, p2, p3, p4, p5) } 25 | } 26 | 27 | fun Function4.createPartialFunction(partial1: Partial = partial(), 28 | partial2: Partial = partial(), 29 | partial3: Partial = partial(), 30 | p4: P4): (P1, P2, P3) -> R { 31 | return { p1: P1, p2: P2, p3: P3 -> this(p1, p2, p3, p4) } 32 | } 33 | 34 | fun Function3.createPartialFunction(partial1: Partial = partial(), 35 | partial2: Partial = partial(), 36 | p3: P3): (P1, P2) -> R { 37 | return { p1: P1, p2: P2 -> this(p1, p2, p3) } 38 | } 39 | 40 | fun Function3.createPartialFunction(partial1: Partial = partial(), 41 | p2: P2, 42 | partial3: Partial = partial()): (P1, P3) -> R { 43 | return { p1: P1, p3: P3 -> this(p1, p2, p3) } 44 | } 45 | 46 | fun Function3.createPartialFunction(p1: P1, 47 | partial2: Partial = partial(), 48 | p3: P3): (P2) -> R { 49 | return { p2: P2 -> this(p1, p2, p3) } 50 | } 51 | 52 | 53 | fun main() { 54 | 55 | val sum = { x: Int, y: Int -> x + y } 56 | 57 | 58 | val addToTwo = sum.createPartialFunction(2) 59 | 60 | 61 | println(addToTwo(5)) 62 | 63 | } -------------------------------------------------------------------------------- /instructor/advanced/org/jetbrains/kotlinworkshop/advanced/_7FunctionalConstructs/_4Composition.kt: -------------------------------------------------------------------------------- 1 | package org.jetbrains.kotlinworkshop.advanced._7FunctionalConstructs 2 | 3 | 4 | // f(g(x)) 5 | fun Function1.compose(g: (RP1) -> FP1): (RP1) -> RF { 6 | return { p1: RP1 -> this(g(p1)) } 7 | } 8 | 9 | fun compose(f: (Int, Int) -> Int, g: (Int) -> Int): (Int, Int) -> Int { 10 | return { p1: Int, p2: Int -> g(f(p1, p2)) } 11 | } 12 | 13 | // g(f(x)) 14 | fun Function1.andThen(f: (RG) -> RF1): (GP1) -> RF1 { 15 | return { p1: GP1 -> f(this(p1)) } 16 | } 17 | 18 | fun compose1(f: (a: Any) -> Any, g: (a: Any) -> Any): (a: Any) -> Any { 19 | return { x: Any -> { g(f(x)) } } 20 | } 21 | 22 | fun sum(x: Int, y: Int) = x + y 23 | 24 | 25 | fun squared(x: Int) = x * x 26 | 27 | 28 | fun main() { 29 | 30 | 31 | val sumSquared = compose(::sum, ::squared) 32 | 33 | println(sumSquared(2, 3)) 34 | 35 | } 36 | 37 | -------------------------------------------------------------------------------- /instructor/advanced/org/jetbrains/kotlinworkshop/advanced/_7FunctionalConstructs/_5Functors.kt: -------------------------------------------------------------------------------- 1 | package org.jetbrains.kotlinworkshop.advanced._7FunctionalConstructs 2 | 3 | 4 | sealed class Maybe { 5 | object None : Maybe() 6 | data class Just(val value: A) : Maybe() 7 | 8 | inline fun fmap(f: (A) -> B): Maybe = when (this) { 9 | is None -> this 10 | is Just -> Just(f(value)) 11 | } 12 | } 13 | 14 | 15 | fun maybeReturnSomething(input: Boolean): Maybe { 16 | return if (input) Maybe.Just(10) else Maybe.None 17 | } 18 | 19 | fun main() { 20 | 21 | 22 | println(Maybe.Just(4).fmap { it + 10 }) 23 | 24 | 25 | val someResult: Maybe = maybeReturnSomething(false) 26 | someResult.fmap { it + 10 } 27 | 28 | println(someResult) 29 | } -------------------------------------------------------------------------------- /instructor/advanced/org/jetbrains/kotlinworkshop/advanced/_7FunctionalConstructs/_6Applicatives.kt: -------------------------------------------------------------------------------- 1 | package org.jetbrains.kotlinworkshop.advanced._7FunctionalConstructs 2 | 3 | 4 | infix fun Maybe<(A) -> B>.apply(f: Maybe): Maybe = 5 | when (this) { 6 | is Maybe.None -> Maybe.None 7 | is Maybe.Just -> f.fmap(this.value) 8 | } 9 | 10 | infix inline fun Array<(A) -> B>.apply(a: Array) = 11 | Array(this.size * a.size) { 12 | this[it / a.size](a[it % a.size]) 13 | } 14 | 15 | 16 | fun main() { 17 | 18 | } 19 | -------------------------------------------------------------------------------- /instructor/advanced/org/jetbrains/kotlinworkshop/advanced/_7FunctionalConstructs/_7Monads.kt: -------------------------------------------------------------------------------- 1 | package org.jetbrains.kotlinworkshop.advanced._7FunctionalConstructs 2 | 3 | 4 | sealed class MaybeMonad { 5 | object None : MaybeMonad() 6 | data class Just(val value: A) : MaybeMonad() 7 | 8 | inline fun fmap(f: (A) -> B): MaybeMonad = when (this) { 9 | is None -> this 10 | is Just -> Just(f(value)) 11 | } 12 | 13 | infix inline fun bind(f: (A) -> MaybeMonad): MaybeMonad = when (this) { 14 | is None -> this 15 | is Just -> f(value) 16 | } 17 | } 18 | 19 | 20 | fun half(a: Int) = when { 21 | a % 2 == 0 -> MaybeMonad.Just(a / 2) 22 | else -> MaybeMonad.None 23 | } 24 | 25 | 26 | fun main() { 27 | MaybeMonad.Just(20) bind ::half 28 | } -------------------------------------------------------------------------------- /instructor/advanced/org/jetbrains/kotlinworkshop/advanced/_8Dsl/_1ExtensionWithInfix.kt: -------------------------------------------------------------------------------- 1 | package org.jetbrains.kotlinworkshop.advanced._8Dsl 2 | 3 | 4 | fun String.toTitleCase(): String { 5 | return this.split(" ").joinToString(" ") { it.capitalize() } 6 | } 7 | 8 | 9 | infix fun String.isTheSameAs(value: String) = this == value 10 | 11 | 12 | fun main() { 13 | 14 | 15 | "Hello".isTheSameAs("Hello") 16 | 17 | "Hello" isTheSameAs "Hello" 18 | 19 | 20 | println("this is a sample string to Title Case it".toTitleCase()) 21 | } 22 | -------------------------------------------------------------------------------- /instructor/advanced/org/jetbrains/kotlinworkshop/advanced/_8Dsl/_2Invoke.kt: -------------------------------------------------------------------------------- 1 | package org.jetbrains.kotlinworkshop.advanced._8Dsl 2 | 3 | 4 | class FooClass { 5 | var name: String = "" 6 | operator fun invoke(name: String) { 7 | println("Hello $name") 8 | } 9 | } 10 | 11 | 12 | fun main() { 13 | val foo = FooClass() 14 | foo("Something") 15 | println(foo.name) 16 | } -------------------------------------------------------------------------------- /instructor/advanced/org/jetbrains/kotlinworkshop/advanced/_8Dsl/_3LambdasWithReceivers.kt: -------------------------------------------------------------------------------- 1 | package org.jetbrains.kotlinworkshop.advanced._8Dsl 2 | 3 | 4 | fun route(path: String, f: RouteHandler.() -> Unit) { 5 | 6 | } 7 | -------------------------------------------------------------------------------- /instructor/advanced/org/jetbrains/kotlinworkshop/advanced/_8Dsl/_4DslSample.kt: -------------------------------------------------------------------------------- 1 | package org.jetbrains.kotlinworkshop.advanced._8Dsl 2 | 3 | 4 | class Request(val method: String, val query: String, val contentType: String) { 5 | operator fun invoke(function: () -> Any) { 6 | TODO("not implemented") //To change body of created functions use File | Settings | File Templates. 7 | } 8 | } 9 | 10 | class Response(var contents: String, var statusCode: Int) { 11 | operator fun invoke(function: () -> Unit): Any { 12 | TODO("not implemented") //To change body of created functions use File | Settings | File Templates. 13 | } 14 | } 15 | 16 | 17 | class RouteHandler(val request: Request, val response: Response) {} 18 | 19 | 20 | fun get(path: String, f: RouteHandler.() -> Unit): RouteHandler.() -> Unit = f 21 | 22 | 23 | fun String.with(handler: Response.() -> Unit): Pair Unit> = this to handler 24 | 25 | 26 | fun main() { 27 | 28 | get("/home") { 29 | if (request.method == "GET") { 30 | response { 31 | 32 | } 33 | } 34 | } 35 | 36 | 37 | } -------------------------------------------------------------------------------- /instructor/advanced/org/jetbrains/kotlinworkshop/advanced/_8Dsl/_5HtmlExample.kt: -------------------------------------------------------------------------------- 1 | package org.jetbrains.kotlinworkshop.advanced._8Dsl 2 | 3 | @DslMarker 4 | annotation class HtmlDsl 5 | 6 | open class Tag(val name: String) { 7 | private val children = mutableListOf() 8 | 9 | protected fun doInit(child: T, init: T.() -> Unit) { 10 | child.init() 11 | children.add(child) 12 | } 13 | 14 | override fun toString() = 15 | "<$name>${children.joinToString("")}" 16 | } 17 | 18 | fun table(init: TABLE.() -> Unit): TABLE { 19 | val table = TABLE() 20 | table.init() 21 | return table 22 | } 23 | 24 | @HtmlDsl 25 | class TABLE : Tag("table") { 26 | fun tr(init: TR.() -> Unit) = doInit(TR(), init) 27 | } 28 | 29 | @HtmlDsl 30 | class TR : Tag("tr") { 31 | fun td(init: TD.() -> Unit) = doInit(TD(), init) 32 | } 33 | 34 | @HtmlDsl 35 | class TD : Tag("td") 36 | 37 | fun createTable(): TABLE { 38 | return table { 39 | tr { 40 | for (i in 1..2) { 41 | td { 42 | } 43 | } 44 | } 45 | } 46 | } 47 | 48 | fun main() { 49 | println(createTable()) 50 | //
51 | } -------------------------------------------------------------------------------- /instructor/advanced/org/jetbrains/kotlinworkshop/advanced/_9Metaprogramming/_1Annotations.kt: -------------------------------------------------------------------------------- 1 | package org.jetbrains.kotlinworkshop.advanced._9Metaprogramming 2 | 3 | 4 | @Target(AnnotationTarget.CLASS) 5 | annotation class Table(val name: String) 6 | 7 | @Target(AnnotationTarget.PROPERTY) 8 | annotation class Field(val name: String) 9 | 10 | 11 | @Table(name = "ContactTable") 12 | data class Contact(val id: Int, @Field(name = "NAME") val name: String, val email: String) 13 | 14 | 15 | fun main() { 16 | 17 | val annotation = Contact::class.annotations.find { it.annotationClass.simpleName == "Table" } 18 | 19 | println(annotation) 20 | 21 | 22 | } 23 | 24 | -------------------------------------------------------------------------------- /instructor/advanced/org/jetbrains/kotlinworkshop/advanced/_9Metaprogramming/_2JavaReflection.kt: -------------------------------------------------------------------------------- 1 | package org.jetbrains.kotlinworkshop.advanced._9Metaprogramming 2 | 3 | import java.lang.reflect.* 4 | 5 | class Transaction(val id: Int, val amount: Double, var description: String = "Default Value") { 6 | fun validate() { 7 | if (amount > 10000) { 8 | println("org.jetbrains.kotlinworkshop.advanced._9Metaprogramming.Transaction is too large") 9 | } 10 | } 11 | } 12 | 13 | fun introspectInstance(obj: Any) { 14 | 15 | println("Class ${obj.javaClass.simpleName}") 16 | println("Properties\n") 17 | obj.javaClass.declaredFields.forEach { 18 | println("${it.name} of type ${it.type}") 19 | } 20 | println("Functions\n") 21 | obj.javaClass.declaredMethods.forEach { 22 | println("${it.name}") 23 | } 24 | 25 | } 26 | 27 | fun getType(obj: Type) { 28 | println(obj.typeName) 29 | } 30 | 31 | fun main() { 32 | getType(Transaction::class.java) 33 | 34 | // introspectInstance(Transaction(1, 200.0, "A simple transaction")) 35 | } -------------------------------------------------------------------------------- /instructor/advanced/org/jetbrains/kotlinworkshop/advanced/_9Metaprogramming/_3KotlinReflection.kt: -------------------------------------------------------------------------------- 1 | package org.jetbrains.kotlinworkshop.advanced._9Metaprogramming 2 | 3 | import kotlin.reflect.* 4 | 5 | fun getKotlinType(obj: KClass<*>) { 6 | println(obj.qualifiedName) 7 | } 8 | 9 | fun main() { 10 | 11 | 12 | /* 13 | val classInfo = Transaction::class 14 | 15 | classInfo.memberProperties.forEach { 16 | println("Property ${it.name} of type ${it.returnType}") 17 | } 18 | 19 | classInfo.constructors.forEach { 20 | println("Constructor ${it.name} - ${it.parameters}") 21 | } 22 | 23 | getKotlinType(Transaction::class) 24 | */ 25 | 26 | val constructor = ::Transaction 27 | 28 | println(constructor) 29 | 30 | 31 | val idParam = constructor.parameters.first { it.name == "id" } 32 | val amountParam = constructor.parameters.first { it.name == "amount" } 33 | 34 | val transaction = constructor.callBy(mapOf(idParam to 1, amountParam to 2000)) 35 | 36 | val trans = Transaction(1, 20.0, "New Value") 37 | 38 | 39 | val nameProperty = Transaction::class.members.find { it.name == "description" } 40 | 41 | } -------------------------------------------------------------------------------- /instructor/introduction/cmdline/Hello.class: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/Kotlin/workshop/37552440e6e6a1f7607ea5722eef1e8d5578d4f5/instructor/introduction/cmdline/Hello.class -------------------------------------------------------------------------------- /instructor/introduction/cmdline/Hello.java: -------------------------------------------------------------------------------- 1 | public class Hello { 2 | public static void main(String[] args) { 3 | System.out.println("Hello, World!"); 4 | } 5 | } 6 | -------------------------------------------------------------------------------- /instructor/introduction/cmdline/HelloKt.class: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/Kotlin/workshop/37552440e6e6a1f7607ea5722eef1e8d5578d4f5/instructor/introduction/cmdline/HelloKt.class -------------------------------------------------------------------------------- /instructor/introduction/cmdline/Hellokt.jar: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/Kotlin/workshop/37552440e6e6a1f7607ea5722eef1e8d5578d4f5/instructor/introduction/cmdline/Hellokt.jar -------------------------------------------------------------------------------- /instructor/introduction/cmdline/META-INF/main.kotlin_module: -------------------------------------------------------------------------------- 1 |  2 | 3 | HelloKt -------------------------------------------------------------------------------- /instructor/introduction/cmdline/hello.kt: -------------------------------------------------------------------------------- 1 | fun main() { 2 | println("Hello, World!") 3 | } 4 | -------------------------------------------------------------------------------- /instructor/introduction/org/jetbrains/kotlinworkshop/introduction/_10Conventions/_1OperatorOverloading.kt: -------------------------------------------------------------------------------- 1 | package org.jetbrains.kotlinworkshop.introduction._10Conventions 2 | 3 | import java.lang.* 4 | 5 | 6 | data class Time(val hours: Int, val mins: Int) { 7 | operator fun plus(time: Time): Time { 8 | val minutes = this.mins + time.mins 9 | val hoursInMinutes = minutes / 60 10 | val remainingMinutes = minutes % 60 11 | val hours = this.hours + time.hours + hoursInMinutes 12 | return Time(hours, remainingMinutes) 13 | } 14 | } 15 | 16 | operator fun StringBuilder.plus(stringBuilder: StringBuilder) { 17 | stringBuilder.forEach { this.append(it) } 18 | } 19 | 20 | data class Point(val x: Int, val y: Int) 21 | 22 | operator fun Point.plus(other: Point): Point { 23 | return Point(x + other.x, y + other.y) 24 | } 25 | 26 | operator fun Point.times(scale: Int): Point { 27 | return Point(x * scale, y * scale) 28 | } 29 | 30 | fun main() { 31 | 32 | val newTime = Time(10, 40) + Time(3, 20) 33 | 34 | println(newTime) 35 | 36 | val sb = StringBuilder() 37 | for (str in sb) { 38 | str + "Value" 39 | } 40 | 41 | val p1 = Point(1, 2) + Point(2, 3) 42 | val p2 = Point(1, 2) * 3 43 | println(p1) 44 | println(p2) 45 | 46 | } -------------------------------------------------------------------------------- /instructor/introduction/org/jetbrains/kotlinworkshop/introduction/_11Generics/_1Basics.kt: -------------------------------------------------------------------------------- 1 | package org.jetbrains.kotlinworkshop.introduction._11Generics 2 | 3 | import org.jetbrains.kotlinworkshop.introduction._Shared.* 4 | 5 | 6 | interface Repository { 7 | fun getById(id: Int): T 8 | fun getAll(): List 9 | } 10 | 11 | fun main() { 12 | 13 | val customerRepo = CustomerRepository() 14 | 15 | val customer = customerRepo.getById(10) 16 | val customers = customerRepo.getAll() 17 | 18 | 19 | } 20 | -------------------------------------------------------------------------------- /instructor/introduction/org/jetbrains/kotlinworkshop/introduction/_11Generics/_2Invariance.kt: -------------------------------------------------------------------------------- 1 | package org.jetbrains.kotlinworkshop.introduction._11Generics 2 | 3 | 4 | fun invariant() { 5 | val elements: MutableList 6 | val strings: MutableList = mutableListOf("A", "B", "C") 7 | 8 | // The line below won't compile 9 | 10 | // elements = strings 11 | } 12 | 13 | -------------------------------------------------------------------------------- /instructor/introduction/org/jetbrains/kotlinworkshop/introduction/_11Generics/_3Covariance.kt: -------------------------------------------------------------------------------- 1 | package org.jetbrains.kotlinworkshop.introduction._11Generics 2 | 3 | 4 | class Consumer { 5 | fun consumeSomething(list: List) { 6 | 7 | } 8 | } 9 | 10 | 11 | -------------------------------------------------------------------------------- /instructor/introduction/org/jetbrains/kotlinworkshop/introduction/_11Generics/_4Contravariance.kt: -------------------------------------------------------------------------------- 1 | package org.jetbrains.kotlinworkshop.introduction._11Generics 2 | 3 | class Producer { 4 | fun produceSomething(): List { 5 | TODO() 6 | } 7 | } 8 | -------------------------------------------------------------------------------- /instructor/introduction/org/jetbrains/kotlinworkshop/introduction/_1Intro/_0Main.kt: -------------------------------------------------------------------------------- 1 | package org.jetbrains.kotlinworkshop.introduction._1Intro 2 | 3 | fun main(args: Array) { 4 | val name = if (args.size > 0) args[0] else "Kotlin" 5 | println("Hello, $name!") 6 | 7 | // ${} 8 | } 9 | -------------------------------------------------------------------------------- /instructor/introduction/org/jetbrains/kotlinworkshop/introduction/_1Intro/_1Variables.kt: -------------------------------------------------------------------------------- 1 | package org.jetbrains.kotlinworkshop.introduction._1Intro 2 | 3 | fun main() { 4 | // read-only 5 | val question: String = 6 | "life, the universe, " + 7 | "and everything" 8 | println("$question?") 9 | 10 | // mutable 11 | var answer = 0 12 | answer = 42 13 | println(answer) 14 | 15 | // answer = "no answer" 16 | 17 | // val is read-only reference, not object 18 | val languages = mutableListOf("Java") 19 | languages.add("Kotlin") 20 | } -------------------------------------------------------------------------------- /instructor/introduction/org/jetbrains/kotlinworkshop/introduction/_1Intro/_2Numbers.kt: -------------------------------------------------------------------------------- 1 | package org.jetbrains.kotlinworkshop.introduction._1Intro 2 | 3 | 4 | fun main() { 5 | 6 | val myLong = 10L 7 | val myFloat = 100F 8 | val myHex = 0x0F 9 | val myBinary = 0b01 10 | 11 | val myInt = 100 12 | val myLongAgain: Long = myInt.toLong() 13 | 14 | } -------------------------------------------------------------------------------- /instructor/introduction/org/jetbrains/kotlinworkshop/introduction/_1Intro/_3Functions.kt: -------------------------------------------------------------------------------- 1 | package org.jetbrains.kotlinworkshop.introduction._1Intro 2 | 3 | fun max(a: Int, b: Int): Int { 4 | return if (a < b) a else b 5 | } 6 | 7 | fun max2(a: Int, b: Int) = if (a < b) a else b 8 | 9 | // default values for arguments 10 | fun sum(a: Int, b: Int, c: Int = 0) = a + b + c 11 | 12 | 13 | // vararg 14 | fun printMany(vararg elements: Int) { 15 | for (element in elements) { 16 | println(element) 17 | } 18 | 19 | doSomething(*elements) 20 | 21 | } 22 | 23 | fun doSomething(vararg elements: Int) { 24 | for (element in elements) { 25 | println("Doing something $element") 26 | } 27 | } 28 | 29 | fun main() { 30 | sum(1, 2) 31 | sum(1, 2, 3) 32 | // named arguments 33 | sum(b = 2, a = 1) 34 | 35 | printMany(1, 2, 3, 4, 5) 36 | } 37 | 38 | 39 | -------------------------------------------------------------------------------- /instructor/introduction/org/jetbrains/kotlinworkshop/introduction/_1Intro/_4LocalFunctions.kt: -------------------------------------------------------------------------------- 1 | package org.jetbrains.kotlinworkshop.introduction._1Intro 2 | 3 | 4 | fun foo(fooParam: String) { 5 | 6 | val outerFunction = "Value" 7 | fun bar(barParam: String) { 8 | 9 | println(barParam) 10 | println(fooParam) 11 | println(outerFunction) 12 | } 13 | 14 | 15 | } 16 | 17 | fun main() { 18 | 19 | foo("Some value") 20 | 21 | 22 | } 23 | -------------------------------------------------------------------------------- /instructor/introduction/org/jetbrains/kotlinworkshop/introduction/_1Intro/_5Constants.kt: -------------------------------------------------------------------------------- 1 | package org.jetbrains.kotlinworkshop.introduction._1Intro 2 | 3 | 4 | val CopyrightName = "JetBrains" 5 | 6 | // known at compile time 7 | const val CopyrightYear = 2017 8 | 9 | 10 | val a = sum(2, 3) -------------------------------------------------------------------------------- /instructor/introduction/org/jetbrains/kotlinworkshop/introduction/_1Intro/_6BasicInterop.kt: -------------------------------------------------------------------------------- 1 | package org.jetbrains.kotlinworkshop.introduction._1Intro 2 | 3 | import org.jetbrains.kotlinworkshop.introduction._Shared.* 4 | 5 | 6 | fun main() { 7 | 8 | val customerJava = CustomerJava(1, "Mary Jane") 9 | customerJava.name 10 | 11 | 12 | } -------------------------------------------------------------------------------- /instructor/introduction/org/jetbrains/kotlinworkshop/introduction/_1Intro/_7FromJava.java: -------------------------------------------------------------------------------- 1 | package org.jetbrains.kotlinworkshop.introduction._1Intro; 2 | 3 | import org.jetbrains.kotlinworkshop.introduction._Shared.Customer; 4 | 5 | public class _7FromJava { 6 | 7 | public static void main(String[] args) { 8 | 9 | Customer customerKotlin = new Customer(1, "Mary Jane"); 10 | 11 | // 12 | int result = _3FunctionsKt.max(2, 3); 13 | 14 | } 15 | } 16 | -------------------------------------------------------------------------------- /instructor/introduction/org/jetbrains/kotlinworkshop/introduction/_2ControlStructures/_1IfAndWhen.kt: -------------------------------------------------------------------------------- 1 | package org.jetbrains.kotlinworkshop.introduction._2ControlStructures 2 | 3 | 4 | enum class Color { 5 | BLUE, ORANGE, RED 6 | } 7 | 8 | fun updateWeather( 9 | celsiusDegrees: Double 10 | ) { 11 | val description: String 12 | val color: Color 13 | when { 14 | celsiusDegrees < 0 -> { 15 | description = "cold" 16 | color = Color.BLUE 17 | } 18 | celsiusDegrees in 0..15 -> { 19 | description = "mild" 20 | color = Color.ORANGE 21 | } 22 | else -> { 23 | description = "hot" 24 | color = Color.RED 25 | } 26 | } 27 | } 28 | 29 | fun updateWeather1(celsiusDegrees: Double) { 30 | val (description, color) = 31 | when { 32 | celsiusDegrees < 0 -> Pair("cold", Color.BLUE) 33 | celsiusDegrees in 0..15 -> "mild" to Color.ORANGE 34 | else -> "hot" to Color.RED 35 | } 36 | } -------------------------------------------------------------------------------- /instructor/introduction/org/jetbrains/kotlinworkshop/introduction/_2ControlStructures/_2Loops.kt: -------------------------------------------------------------------------------- 1 | package org.jetbrains.kotlinworkshop.introduction._2ControlStructures 2 | 3 | fun whileLoop() { 4 | fun condition() = true 5 | 6 | while (condition()) { 7 | /*...​*/ 8 | } 9 | 10 | do { 11 | /*...​*/ 12 | } while (condition()) 13 | } 14 | 15 | 16 | fun forLoop() { 17 | val list = listOf(1, 2, 3) 18 | for (element in list) { 19 | print(element) 20 | } 21 | 22 | for (i in 1..9) { // including 9 23 | print(i) 24 | } 25 | 26 | // excluding 10 (the same as 1..9) 27 | for (i in 1 until 10) { 28 | print(i) 29 | } 30 | 31 | for (i in 9 downTo 1 step 2) { 32 | print(i) 33 | } 34 | } 35 | 36 | fun main() { 37 | forLoop() 38 | } -------------------------------------------------------------------------------- /instructor/introduction/org/jetbrains/kotlinworkshop/introduction/_2ControlStructures/_3Iterating.kt: -------------------------------------------------------------------------------- 1 | package org.jetbrains.kotlinworkshop.introduction._2ControlStructures 2 | 3 | fun iteratingOverCollection() { 4 | val list = listOf("a", "b") 5 | for (s in list) { 6 | println(s) 7 | } 8 | } 9 | 10 | fun iteratingOverMap() { 11 | val map = mapOf(1 to "one", 2 to "two", 3 to "three") 12 | 13 | for ((key, value) in map) { 14 | println("$key = $value") 15 | } 16 | } 17 | 18 | fun iteratingOverCollectionWithIndex() { 19 | for ((index, element) in listOf("a", "b", "c").withIndex()) { 20 | println("$index $element") 21 | } 22 | } 23 | 24 | fun main() { 25 | iteratingOverCollection() 26 | iteratingOverMap() 27 | iteratingOverCollectionWithIndex() 28 | } -------------------------------------------------------------------------------- /instructor/introduction/org/jetbrains/kotlinworkshop/introduction/_2ControlStructures/_4Ranges.kt: -------------------------------------------------------------------------------- 1 | package org.jetbrains.kotlinworkshop.introduction._2ControlStructures 2 | 3 | fun isLetter(c: Char) = c in 'a'..'z' || c in 'A'..'Z' 4 | // c in 'a'..'z' 5 | // is compiled to: 6 | // 'a' <= c && c <= 'z' 7 | 8 | fun isNotDigit(c: Char) = c !in '0'..'9' 9 | 10 | fun main() { 11 | println(isLetter('q')) // true 12 | println(isNotDigit('x')) // true 13 | } 14 | 15 | fun recognize(c: Char) = when (c) { 16 | in '0'..'9' -> "It's a digit!" 17 | in 'a'..'z', in 'A'..'Z' -> "It's a letter!" 18 | else -> "I don't know…​" 19 | } -------------------------------------------------------------------------------- /instructor/introduction/org/jetbrains/kotlinworkshop/introduction/_3Classes/_10NestedClasses.kt: -------------------------------------------------------------------------------- 1 | package org.jetbrains.kotlinworkshop.introduction._3Classes 2 | 3 | 4 | class Outer { 5 | private val bar: Int = 1 6 | 7 | class Nested { 8 | fun foo() = 2 9 | } 10 | } 11 | 12 | val outer = Outer.Nested().foo() // == 2 13 | 14 | class OuterWithInner { 15 | private val bar: Int = 1 16 | 17 | inner class Inner { 18 | fun foo() = bar 19 | } 20 | } 21 | 22 | val outerWithInner = OuterWithInner().Inner().foo() // == 1 -------------------------------------------------------------------------------- /instructor/introduction/org/jetbrains/kotlinworkshop/introduction/_3Classes/_11TypeAliases.kt: -------------------------------------------------------------------------------- 1 | package org.jetbrains.kotlinworkshop.introduction._3Classes 2 | 3 | 4 | typealias CustomerName = String 5 | 6 | 7 | // Example of using typealias for rename with @Deprecated 8 | 9 | 10 | class BaseCustomer // before was called BasicCustomer 11 | 12 | @Deprecated("BasicCustomer is now called BaseCustomer", replaceWith = ReplaceWith("BaseCustomer")) 13 | typealias BasicCustomer = BaseCustomer 14 | 15 | 16 | 17 | 18 | fun main() { 19 | 20 | 21 | val customer = BasicCustomer() 22 | 23 | } -------------------------------------------------------------------------------- /instructor/introduction/org/jetbrains/kotlinworkshop/introduction/_3Classes/_1Classes.kt: -------------------------------------------------------------------------------- 1 | package org.jetbrains.kotlinworkshop.introduction._3Classes 2 | 3 | // similar to javaCode.Person 4 | 5 | class AnotherPerson(val name: String, val age: Int) 6 | 7 | fun main() { 8 | // no new keyword, constructor is called as a regular function 9 | val person = AnotherPerson("Alice", 26) 10 | println(person.name) 11 | } -------------------------------------------------------------------------------- /instructor/introduction/org/jetbrains/kotlinworkshop/introduction/_3Classes/_2PrimaryConstructor.kt: -------------------------------------------------------------------------------- 1 | package org.jetbrains.kotlinworkshop.introduction._3Classes 2 | 3 | /* short syntax */ 4 | class Person1(val name: String) 5 | 6 | /* full syntax */ 7 | // constructor parameter 8 | class Person2(name: String) { 9 | 10 | // property 11 | val name: String 12 | 13 | // constructor body 14 | init { 15 | this.name = name 16 | } 17 | } 18 | -------------------------------------------------------------------------------- /instructor/introduction/org/jetbrains/kotlinworkshop/introduction/_3Classes/_3Constructors.kt: -------------------------------------------------------------------------------- 1 | package org.jetbrains.kotlinworkshop.introduction._3Classes 2 | 3 | class Rectangle(val height: Int, val width: Int) { 4 | 5 | //secondary constructors 6 | constructor(side: Int) : this(side, side) 7 | } 8 | 9 | fun main() { 10 | val rectangle = Rectangle(42) 11 | println(rectangle.height == rectangle.width) 12 | } -------------------------------------------------------------------------------- /instructor/introduction/org/jetbrains/kotlinworkshop/introduction/_3Classes/_4Properties.kt: -------------------------------------------------------------------------------- 1 | package org.jetbrains.kotlinworkshop.introduction._3Classes 2 | 3 | class AnotherRectangle(val height: Int, val width: Int) { 4 | 5 | // you can redefine getter (and setter) 6 | val isSquare: Boolean 7 | get() { 8 | return height == width 9 | } 10 | } 11 | 12 | fun main() { 13 | val rectangle = AnotherRectangle(41, 43) 14 | println(rectangle.isSquare) 15 | } -------------------------------------------------------------------------------- /instructor/introduction/org/jetbrains/kotlinworkshop/introduction/_3Classes/_5MutableProperty.kt: -------------------------------------------------------------------------------- 1 | package org.jetbrains.kotlinworkshop.introduction._3Classes 2 | 3 | class LengthCounter { 4 | var counter: Int = 0 5 | private set 6 | 7 | fun addWord(word: String) { 8 | counter += word.length 9 | } 10 | } 11 | 12 | fun main() { 13 | val lengthCounter = LengthCounter() 14 | lengthCounter.addWord("Hi!") 15 | println(lengthCounter.counter) 16 | 17 | StateLogger().state = true 18 | } 19 | 20 | class StateLogger { 21 | var state = false 22 | set(value) { 23 | println("state has changed") 24 | field = value 25 | } 26 | } -------------------------------------------------------------------------------- /instructor/introduction/org/jetbrains/kotlinworkshop/introduction/_3Classes/_6Equals.kt: -------------------------------------------------------------------------------- 1 | package org.jetbrains.kotlinworkshop.introduction._3Classes 2 | 3 | fun main() { 4 | val set1 = setOf(1, 2, 3) 5 | val set2 = setOf(1, 2, 3) 6 | 7 | // checks reference equality 8 | println(set1 === set2) 9 | 10 | // calls equals 11 | println(set1 == set2) 12 | } -------------------------------------------------------------------------------- /instructor/introduction/org/jetbrains/kotlinworkshop/introduction/_3Classes/_7Tuples.kt: -------------------------------------------------------------------------------- 1 | package org.jetbrains.kotlinworkshop.introduction._3Classes 2 | 3 | 4 | fun main() { 5 | 6 | val countryAndCity = Pair("Spain", "Madrid") 7 | 8 | countryAndCity.first 9 | countryAndCity.component1() 10 | 11 | val countryAndCityAndContinent = Triple("Spain", "Madrid", "Europe") 12 | 13 | 14 | } -------------------------------------------------------------------------------- /instructor/introduction/org/jetbrains/kotlinworkshop/introduction/_3Classes/_8DataClass.kt: -------------------------------------------------------------------------------- 1 | package org.jetbrains.kotlinworkshop.introduction._3Classes 2 | 3 | // Adding data makes the compiler generate useful methods 4 | // such as equals, hashCode, toString. 5 | data class Person( 6 | val name: String, 7 | val age: Int) 8 | 9 | fun main() { 10 | val person1 = Person("Alice", 21) 11 | val person2 = Person("Alice", 21) 12 | println(person1) 13 | println(person1 == person2) 14 | } -------------------------------------------------------------------------------- /instructor/introduction/org/jetbrains/kotlinworkshop/introduction/_3Classes/_9Destructuring.kt: -------------------------------------------------------------------------------- 1 | package org.jetbrains.kotlinworkshop.introduction._3Classes 2 | 3 | 4 | fun main() { 5 | 6 | val (country, city) = Pair("Spain", "Madrid") 7 | 8 | 9 | val (country1, city1, continent1) = Triple("Spain", "Madrid", "Europe") 10 | 11 | val (_, age) = Person("Joe Smith", 42) 12 | 13 | } -------------------------------------------------------------------------------- /instructor/introduction/org/jetbrains/kotlinworkshop/introduction/_3Classes/javaCode/Person.java: -------------------------------------------------------------------------------- 1 | package org.jetbrains.kotlinworkshop.introduction._3Classes.javaCode; 2 | 3 | public class Person { 4 | private final String name; 5 | private final int age; 6 | 7 | public Person(String name, int age) { 8 | this.name = name; 9 | this.age = age; 10 | } 11 | 12 | public String getName() { 13 | return name; 14 | } 15 | 16 | public int getAge() { 17 | return age; 18 | } 19 | } -------------------------------------------------------------------------------- /instructor/introduction/org/jetbrains/kotlinworkshop/introduction/_3Classes/javaCode/Rectangle.java: -------------------------------------------------------------------------------- 1 | package org.jetbrains.kotlinworkshop.introduction._3Classes.javaCode; 2 | 3 | public class Rectangle { 4 | private final int width; 5 | private final int height; 6 | 7 | public Rectangle(int width, int height) { 8 | this.width = width; 9 | this.height = height; 10 | } 11 | 12 | public int getWidth() { 13 | return width; 14 | } 15 | 16 | public int getHeight() { 17 | return height; 18 | } 19 | 20 | public boolean isSquare() { 21 | return width == height; 22 | } 23 | } 24 | -------------------------------------------------------------------------------- /instructor/introduction/org/jetbrains/kotlinworkshop/introduction/_4Hierarchies/_1Interfaces.kt: -------------------------------------------------------------------------------- 1 | package org.jetbrains.kotlinworkshop.introduction._4Hierarchies 2 | 3 | import org.jetbrains.kotlinworkshop.introduction._Shared.* 4 | 5 | interface CustomerRepository { 6 | val isEmpty: Boolean 7 | get() = true 8 | 9 | fun store(obj: Customer) { 10 | // implement code to store 11 | } 12 | 13 | fun getById(id: Int): Customer 14 | } 15 | 16 | -------------------------------------------------------------------------------- /instructor/introduction/org/jetbrains/kotlinworkshop/introduction/_4Hierarchies/_2AbstractClasses.kt: -------------------------------------------------------------------------------- 1 | package org.jetbrains.kotlinworkshop.introduction._4Hierarchies 2 | 3 | 4 | abstract class StoredEntity { 5 | val isActive = true 6 | abstract fun store() 7 | fun status(): String { 8 | return isActive.toString() 9 | } 10 | 11 | } 12 | 13 | class Employee : StoredEntity() { 14 | override fun store() { 15 | throw UnsupportedOperationException("not implemented") //To change body of created functions use File | Settings | File Templates. 16 | } 17 | 18 | } 19 | 20 | 21 | fun main() { 22 | val se = Employee() 23 | se.isActive 24 | se.status() 25 | } -------------------------------------------------------------------------------- /instructor/introduction/org/jetbrains/kotlinworkshop/introduction/_4Hierarchies/_3ClassInheritance.kt: -------------------------------------------------------------------------------- 1 | package org.jetbrains.kotlinworkshop.introduction._4Hierarchies 2 | 3 | 4 | open class Person() { 5 | open fun validate() { 6 | 7 | } 8 | } 9 | 10 | open class OpenCustomer() : Person() { 11 | final override fun validate() { 12 | 13 | } 14 | } 15 | 16 | class SpecialCustomer : OpenCustomer() { 17 | 18 | } 19 | 20 | data class CustomerEntity(val name: String) : Person() 21 | 22 | fun main() { 23 | 24 | val customer = OpenCustomer() 25 | 26 | customer.validate() 27 | } -------------------------------------------------------------------------------- /instructor/introduction/org/jetbrains/kotlinworkshop/introduction/_5Nullability/_1Nullability.kt: -------------------------------------------------------------------------------- 1 | package org.jetbrains.kotlinworkshop.introduction._5Nullability 2 | 3 | fun main() { 4 | 5 | val s1: String = "always not null" 6 | val s2: String? = null 7 | 8 | val i1: Int = s1.length 9 | // s2.length 10 | 11 | if (s2 != null) s2.length 12 | s2?.length 13 | 14 | val i2: Int? = if (s2 != null) s2.length else null 15 | val i3: Int? = s2?.length 16 | 17 | val i4: Int? = if (s2 != null) s2.length else 0 18 | val i5: Int = s2?.length ?: 0 19 | 20 | s2!! 21 | } 22 | 23 | fun test1(s: String?) { 24 | if (s == null) return 25 | s.length 26 | } 27 | 28 | fun test2(s: String?) { 29 | if (s == null) fail() 30 | s.length 31 | } 32 | 33 | fun test3(s: String?) { 34 | val i: Int = s?.length ?: fail() 35 | } 36 | 37 | fun fail(): Nothing = 38 | throw UnsupportedOperationException() 39 | 40 | fun notImplemented() { 41 | TODO() 42 | } -------------------------------------------------------------------------------- /instructor/introduction/org/jetbrains/kotlinworkshop/introduction/_5Nullability/_2Safecast.kt: -------------------------------------------------------------------------------- 1 | package org.jetbrains.kotlinworkshop.introduction._5Nullability 2 | 3 | class A(val value: Int) 4 | 5 | fun foo(a: Any?) = (a as? A)?.value 6 | 7 | fun main() { 8 | println(foo(A(42))) // 42 9 | println(foo(42)) // null 10 | println(foo(null)) // null 11 | } -------------------------------------------------------------------------------- /instructor/introduction/org/jetbrains/kotlinworkshop/introduction/_5Nullability/_3LateInit.kt: -------------------------------------------------------------------------------- 1 | package org.jetbrains.kotlinworkshop.introduction._5Nullability 2 | 3 | 4 | class Dependency 5 | class Consumer { 6 | lateinit var dependency: Dependency 7 | 8 | fun usingDependency() { 9 | 10 | } 11 | 12 | } -------------------------------------------------------------------------------- /instructor/introduction/org/jetbrains/kotlinworkshop/introduction/_6Extensions/_1Extensions.kt: -------------------------------------------------------------------------------- 1 | //@file:JvmName("StringUtil") 2 | package org.jetbrains.kotlinworkshop.introduction._6Extensions 3 | 4 | fun String.lastChar() = 5 | this.get(this.length - 1) 6 | 7 | // 'this' can be omitted 8 | fun String.lastChar1() = 9 | get(length - 1) 10 | 11 | fun test() { 12 | // visible in completion 13 | "abc".lastChar() 14 | } 15 | 16 | // Infix 17 | infix fun String.isEqual(value: String) = this == value 18 | -------------------------------------------------------------------------------- /instructor/introduction/org/jetbrains/kotlinworkshop/introduction/_7Lambdas/_1HigherOrder.kt: -------------------------------------------------------------------------------- 1 | package org.jetbrains.kotlinworkshop.introduction._7Lambdas 2 | 3 | 4 | fun higherOrder(value: String, op: (String) -> String): String { 5 | println("Executing the operation $op") 6 | return op(value) 7 | } 8 | 9 | fun lowerCase(value: String) = value.toLowerCase() 10 | 11 | fun main() { 12 | println(higherOrder("HELLO", ::lowerCase)) 13 | } 14 | -------------------------------------------------------------------------------- /instructor/introduction/org/jetbrains/kotlinworkshop/introduction/_7Lambdas/_2Lambdas.kt: -------------------------------------------------------------------------------- 1 | package lambdas 2 | 3 | fun basicSyntax() { 4 | val sum = { x: Int, y: Int -> x + y } 5 | 6 | val sum1: (Int, Int) -> Int = { x, y -> x + y } 7 | 8 | println(sum(1, 2)) // 3 9 | } 10 | 11 | fun shortSyntax() { 12 | val string = "one, two, three" 13 | 14 | println(string.filter({ c: Char -> c in 'a'..'z' })) // "onetwothree" 15 | 16 | string.filter() { c: Char -> c in 'a'..'z' } 17 | 18 | string.filter { c: Char -> c in 'a'..'z' } 19 | 20 | string.filter { c -> c in 'a'..'z' } 21 | 22 | string.filter { it in 'a'..'z' } 23 | 24 | string.filter { 25 | it in 'a'..'z' 26 | } 27 | 28 | val s = "abCDa" 29 | 30 | println(s.filter { it in 'a'..'z' }) // aba 31 | println(s.count { it in 'a'..'z' }) //3 32 | 33 | "abCDa".any { it in '1'..'9' } // false 34 | "abCDa1".any { it in '1'..'9' } // true 35 | // true if there at least one character satisfying the predicate 36 | 37 | "abCDa".all { it.toInt() < 200 } 38 | "abd33".find { it > 'c' } // d 39 | 40 | for ((index, ch) in "abc".withIndex()) { 41 | 42 | } 43 | 44 | println("abcd".zip("1234")) 45 | 46 | "abCDa".any { it in 'a'..'z' } 47 | "abCDa".count { it in 'a'..'z' } 48 | "abCDa".find { it in 'a'..'z' } 49 | "abCDa".zip("79371").joinToString() 50 | } 51 | 52 | fun main() { 53 | basicSyntax() 54 | shortSyntax() 55 | } -------------------------------------------------------------------------------- /instructor/introduction/org/jetbrains/kotlinworkshop/introduction/_7Lambdas/_3DestructuringInLambdas.kt: -------------------------------------------------------------------------------- 1 | package org.jetbrains.kotlinworkshop.introduction._7Lambdas 2 | 3 | fun main() { 4 | val map = mapOf(1 to "one", 2 to "two") 5 | map.forEach { entry -> 6 | val (key, value) = entry 7 | println(value) 8 | } 9 | map.forEach { (key, value) -> 10 | println(value) 11 | } 12 | map.forEach { (_, value) -> 13 | println(value) 14 | } 15 | } -------------------------------------------------------------------------------- /instructor/introduction/org/jetbrains/kotlinworkshop/introduction/_7Lambdas/_4AnonymousFunctions.kt: -------------------------------------------------------------------------------- 1 | package org.jetbrains.kotlinworkshop.introduction._7Lambdas 2 | 3 | 4 | fun op(x: Int, op: (Int) -> Int): Int { 5 | 6 | return op(x) 7 | } 8 | 9 | fun main() { 10 | 11 | op(3, { x -> x * x }) 12 | 13 | op(2, fun(x): Int { 14 | 15 | if (x > 10) { 16 | return 0 17 | } else { 18 | return x * x 19 | } 20 | 21 | }) 22 | 23 | } -------------------------------------------------------------------------------- /instructor/introduction/org/jetbrains/kotlinworkshop/introduction/_8Delegation/_1ClassDelegation.kt: -------------------------------------------------------------------------------- 1 | package org.jetbrains.kotlinworkshop.introduction._8Delegation 2 | 3 | import org.jetbrains.kotlinworkshop.introduction._Shared.* 4 | 5 | 6 | interface Repository { 7 | fun getById(id: Int): Customer 8 | fun getAll(): List 9 | } 10 | 11 | interface Logger { 12 | fun logAll() 13 | } 14 | 15 | class Controller(repository: Repository, logger: Logger) : Repository by repository, Logger by logger { 16 | 17 | 18 | } -------------------------------------------------------------------------------- /instructor/introduction/org/jetbrains/kotlinworkshop/introduction/_8Delegation/_2LazyProperty.kt: -------------------------------------------------------------------------------- 1 | package org.jetbrains.kotlinworkshop.introduction._8Delegation 2 | 3 | class LazyProperty { 4 | val lazy: Int by lazy { 5 | println("Calculate the value") 6 | 42 7 | } 8 | } 9 | 10 | fun main() { 11 | println("--- creation ---") 12 | val property = LazyProperty() 13 | 14 | println("--- first access ---") 15 | property.lazy 16 | 17 | println("--- second access ---") 18 | property.lazy 19 | } -------------------------------------------------------------------------------- /instructor/introduction/org/jetbrains/kotlinworkshop/introduction/_8Delegation/_3Observable.kt: -------------------------------------------------------------------------------- 1 | package org.jetbrains.kotlinworkshop.introduction._8Delegation 2 | 3 | import kotlin.properties.* 4 | import kotlin.reflect.* 5 | 6 | class Person( 7 | val name: String, age: Int, salary: Int 8 | ) { 9 | private val observer = { 10 | prop: KProperty<*>, oldValue: Int, newValue: Int -> 11 | println("Property value $oldValue has changed to $newValue") 12 | } 13 | var age: Int by Delegates.observable(age, observer) 14 | var salary: Int by Delegates.observable(salary, observer) 15 | } 16 | 17 | fun main() { 18 | val person = Person("Alice", 25, 2000) 19 | person.age++ 20 | person.salary += 100 21 | } -------------------------------------------------------------------------------- /instructor/introduction/org/jetbrains/kotlinworkshop/introduction/_8Delegation/_4CustomDelegation.kt: -------------------------------------------------------------------------------- 1 | package org.jetbrains.kotlinworkshop.introduction._8Delegation 2 | 3 | import kotlin.reflect.* 4 | 5 | 6 | class Service { 7 | 8 | var someProperty: String by ExternalFunctionality() 9 | 10 | 11 | } 12 | 13 | class ExternalFunctionality { 14 | 15 | var backingField = "Default" 16 | operator fun getValue(service: Service, property: KProperty<*>): String { 17 | println("getValue called with params: \n" + 18 | "service: $service\n" + 19 | "property: ${property.name}" 20 | ) 21 | return backingField 22 | } 23 | 24 | operator fun setValue(service: Service, property: KProperty<*>, value: String) { 25 | backingField = value 26 | } 27 | 28 | } 29 | -------------------------------------------------------------------------------- /instructor/introduction/org/jetbrains/kotlinworkshop/introduction/_9Functional/_1ListOperators.kt: -------------------------------------------------------------------------------- 1 | package org.jetbrains.kotlinworkshop.introduction._9Functional 2 | 3 | 4 | fun head(list: List): T { 5 | return when (list.count()) { 6 | 0 -> 7 | throw IllegalArgumentException("Cannot ask for head on empty list") 8 | else -> list[0] 9 | } 10 | } 11 | 12 | 13 | fun cons(element: T, list: List): List { 14 | return when (list.count()) { 15 | 0 -> listOf(element) 16 | 1 -> listOf(element, head(list)) 17 | else -> listOf(element).plus(list) 18 | } 19 | } 20 | 21 | 22 | fun tail(list: List): List { 23 | return when (list.count()) { 24 | 0 -> throw IllegalArgumentException("Cannot ask for tail on empty list") 25 | 1 -> emptyList() 26 | else -> list.drop(1) 27 | } 28 | } 29 | -------------------------------------------------------------------------------- /instructor/introduction/org/jetbrains/kotlinworkshop/introduction/_9Functional/_2Folds.kt: -------------------------------------------------------------------------------- 1 | package org.jetbrains.kotlinworkshop.introduction._9Functional 2 | 3 | 4 | fun maxNumbers(list: List): Int { 5 | when (list.count()) { 6 | 0 -> throw IllegalArgumentException("This list is empty") 7 | 1 -> return list[0] 8 | else -> return Math.max(list[0], maxNumbers(tail(list))) 9 | 10 | } 11 | } 12 | 13 | 14 | fun maxNumbersFold(list: List): Int { 15 | return list.fold(0, { x, y -> Math.max(x, y) }) 16 | } -------------------------------------------------------------------------------- /instructor/introduction/org/jetbrains/kotlinworkshop/introduction/_9Functional/_3RefactoringFunctional.kt: -------------------------------------------------------------------------------- 1 | package org.jetbrains.kotlinworkshop.introduction._9Functional 2 | 3 | 4 | fun itDoesSomething(elements: List): HashMap { 5 | var i = 0 6 | val results = hashMapOf() 7 | while (i < elements.size) { 8 | val element = results[elements[i]] 9 | if (element != null) { 10 | results[elements[i]] = element + 1 11 | } else { 12 | results[elements[i]] = 1 13 | } 14 | i++ 15 | } 16 | return results 17 | } 18 | 19 | 20 | fun itDoesSomethingAlso(elements: List): List> { 21 | return elements.groupBy { 22 | it 23 | }.map { 24 | Pair(it.key, it.value.count()) 25 | } 26 | } 27 | -------------------------------------------------------------------------------- /instructor/introduction/org/jetbrains/kotlinworkshop/introduction/_9Functional/_4RemovingState.kt: -------------------------------------------------------------------------------- 1 | package org.jetbrains.kotlinworkshop.introduction._9Functional 2 | 3 | import org.jetbrains.kotlinworkshop.introduction._Shared.* 4 | 5 | 6 | // Removing for Loop 7 | 8 | fun topAlbums_v1(albums: List): List { 9 | val hits = arrayListOf() 10 | for (album in albums) { 11 | if (album.chartUK == 1 || album.chartUS == 1) { 12 | hits.add(album) 13 | } 14 | } 15 | return hits 16 | } 17 | 18 | // Moving towards a functional approach (passing moving part) 19 | 20 | fun topAlbums_v2(albums: List): List { 21 | val hits = arrayListOf() 22 | albums.forEach { album -> 23 | if (album.chartUK == 1 || album.chartUS == 1) { 24 | hits.add(album) 25 | } 26 | } 27 | return hits 28 | } 29 | 30 | // Clean up 31 | 32 | fun topAlbums_v3(albums: List): List { 33 | val hits = arrayListOf() 34 | albums.forEach { 35 | if (it.chartUK == 1 || it.chartUS == 1) { 36 | hits.add(it) 37 | } 38 | } 39 | return hits 40 | } 41 | 42 | // Focusing on actual intent 43 | 44 | fun topAlbums_v4(albums: List): List { 45 | return albums.filter { album -> 46 | (album.chartUK == 1 || album.chartUS == 1) 47 | } 48 | } 49 | 50 | -------------------------------------------------------------------------------- /instructor/introduction/org/jetbrains/kotlinworkshop/introduction/_9Functional/_5TransformingData.kt: -------------------------------------------------------------------------------- 1 | package org.jetbrains.kotlinworkshop.introduction._9Functional 2 | 3 | import org.jetbrains.kotlinworkshop.introduction._Shared.* 4 | 5 | 6 | // Adding an intermediate structure 7 | 8 | fun hitYears_v1(albums: List): List { 9 | val hits = albums.filter { it.chartUS == 1 || it.chartUK == 1 } 10 | val years = arrayListOf() 11 | hits.forEach { 12 | years.add(it.year) 13 | } 14 | return years 15 | } 16 | 17 | // Using transformation functions 18 | 19 | fun hitYears_v2(albums: List): List { 20 | return albums.filter { it.chartUS == 1 || it.chartUK == 1 }.map { it.year } 21 | } 22 | 23 | -------------------------------------------------------------------------------- /instructor/introduction/org/jetbrains/kotlinworkshop/introduction/_9Functional/_6VariousPatterns.kt: -------------------------------------------------------------------------------- 1 | package org.jetbrains.kotlinworkshop.introduction._9Functional 2 | 3 | 4 | data class Customer(val id: String, val name: String, val type: String, val country: String) 5 | 6 | 7 | // Filter Pattern 8 | class CustomerFilter { 9 | fun filterByName(customers: List, name: String): List { 10 | val matchedCustomers = arrayListOf() 11 | for (customer in customers) { 12 | if (customer.name == name) { 13 | matchedCustomers.add(customer) 14 | } 15 | } 16 | return matchedCustomers 17 | } 18 | 19 | fun filterByCountry(customers: List, country: String): List { 20 | val matchedCustomers = arrayListOf() 21 | for (customer in customers) { 22 | if (customer.country == country) { 23 | matchedCustomers.add(customer) 24 | } 25 | } 26 | return matchedCustomers 27 | } 28 | } 29 | 30 | 31 | // Strategy Pattern 32 | interface SortAlgorithm { 33 | fun > sort(list: List): List 34 | } 35 | 36 | class QuickSort : SortAlgorithm { 37 | override fun > sort(list: List): List { 38 | TODO("not implemented") //To change body of created functions use File | Settings | File Templates. 39 | } 40 | } 41 | 42 | class BubbleSort : SortAlgorithm { 43 | override fun > sort(list: List): List { 44 | TODO("not implemented") //To change body of created functions use File | Settings | File Templates. 45 | } 46 | 47 | } 48 | 49 | 50 | // Template Patterns 51 | abstract class Record { 52 | abstract fun edit() 53 | abstract fun save() 54 | fun checkPermissions() { 55 | 56 | } 57 | 58 | fun modify() { 59 | checkPermissions() 60 | edit() 61 | save() 62 | } 63 | } 64 | 65 | class CustomerRecord : Record() { 66 | override fun edit() { 67 | TODO("not implemented") //To change body of created functions use File | Settings | File Templates. 68 | } 69 | 70 | override fun save() { 71 | TODO("not implemented") //To change body of created functions use File | Settings | File Templates. 72 | } 73 | 74 | } 75 | 76 | class InvoiceRecord : Record() { 77 | override fun edit() { 78 | TODO("not implemented") //To change body of created functions use File | Settings | File Templates. 79 | } 80 | 81 | override fun save() { 82 | TODO("not implemented") //To change body of created functions use File | Settings | File Templates. 83 | } 84 | 85 | } 86 | 87 | 88 | // Clean-ups > using statement 89 | -------------------------------------------------------------------------------- /instructor/introduction/org/jetbrains/kotlinworkshop/introduction/_9Functional/_7TailRecursion.kt: -------------------------------------------------------------------------------- 1 | package org.jetbrains.kotlinworkshop.introduction._9Functional 2 | 3 | 4 | fun factorial(number: Int): Int { 5 | when (number) { 6 | 0, 1 -> return 1 7 | else -> return number * factorial(number - 1) 8 | } 9 | } 10 | 11 | 12 | tailrec fun factorialTR(number: Int, accumulator: Int = 1): Int { 13 | when (number) { 14 | 0 -> return accumulator 15 | else -> return factorialTR(number - 1, accumulator * number) 16 | } 17 | } 18 | 19 | 20 | fun main() { 21 | println(factorial(5)) 22 | println(factorialTR(5)) 23 | } -------------------------------------------------------------------------------- /instructor/introduction/org/jetbrains/kotlinworkshop/introduction/_9Functional/_8Memoisation.kt: -------------------------------------------------------------------------------- 1 | package org.jetbrains.kotlinworkshop.introduction._9Functional 2 | 3 | 4 | fun fibonnaciRecursive(n: Long): Long { 5 | return when (n) { 6 | 0L, 1L -> n 7 | else -> fibonnaciRecursive(n - 1) + fibonnaciRecursive(n - 2) 8 | } 9 | } 10 | 11 | fun fibonacciIterative(n: Long): Long { 12 | var a = 0L 13 | var b = 1L 14 | for (i in 0..n - 1) { 15 | val temp = a 16 | a = b 17 | b = temp + a 18 | } 19 | return a 20 | } 21 | 22 | 23 | val cache = hashMapOf(0L to 0L, 1L to 1L) 24 | 25 | fun fibonacciMemoised(n: Long): Long { 26 | return if (cache.containsKey(n)) { 27 | cache.getValue(n) 28 | } else { 29 | val result = fibonacciMemoised(n - 1) + fibonacciMemoised(n - 2) 30 | cache[n] = result 31 | result 32 | } 33 | } 34 | 35 | fun main() { 36 | println(fibonacciMemoised(560)) 37 | } -------------------------------------------------------------------------------- /instructor/introduction/org/jetbrains/kotlinworkshop/introduction/_Shared/AlbumData.kt: -------------------------------------------------------------------------------- 1 | package org.jetbrains.kotlinworkshop.introduction._Shared 2 | 3 | 4 | data class Album(val title: String, val year: Int, val chartUK: Int, val chartUS: Int, val tracks: List = listOf()) 5 | 6 | data class Track(val title: String, val durationInSeconds: Int) 7 | 8 | val albums = listOf( 9 | Album("The Dark Side of the Moon", 1973, 2, 1, 10 | listOf(Track("Speak to Me", 90), 11 | Track("Breathe", 163), 12 | Track("On he Run", 216), 13 | Track("Time", 421), 14 | Track("The Great Gig in the Sky", 276), 15 | Track("Money", 382), 16 | Track("Us and Them", 462), 17 | Track("Any Color You Like", 205), 18 | Track("Brain Damage", 228), 19 | Track("Eclipse", 123) 20 | )), 21 | Album("The Wall", 1979, 3, 1), 22 | Album("Wish You Were Here", 1975, 1, 1), 23 | Album("Animals", 1977, 2, 3), 24 | Album("The Piper at the Gates of Dawn", 1967, 6, 131), 25 | Album("The Final Cut", 1983, 1, 6), 26 | Album("Meddle", 1971, 3, 70), 27 | Album("Atom Heart Mother", 1970, 1, 55), 28 | Album("Ummagumma", 1969, 5, 74), 29 | Album("A Sauceful of Secrets", 1968, 9, 0), 30 | Album("More", 1969, 9, 153)) 31 | -------------------------------------------------------------------------------- /instructor/introduction/org/jetbrains/kotlinworkshop/introduction/_Shared/Customer.kt: -------------------------------------------------------------------------------- 1 | package org.jetbrains.kotlinworkshop.introduction._Shared 2 | 3 | 4 | class Customer(val id: Int, val name: String) -------------------------------------------------------------------------------- /instructor/introduction/org/jetbrains/kotlinworkshop/introduction/_Shared/CustomerJava.java: -------------------------------------------------------------------------------- 1 | package org.jetbrains.kotlinworkshop.introduction._Shared; 2 | 3 | public class CustomerJava { 4 | public CustomerJava(int id, String name) { 5 | this.id = id; 6 | this.name = name; 7 | } 8 | 9 | public int getId() { 10 | return id; 11 | } 12 | 13 | public void setId(int id) { 14 | this.id = id; 15 | } 16 | 17 | public String getName() { 18 | return name; 19 | } 20 | 21 | public void setName(String name) { 22 | this.name = name; 23 | } 24 | 25 | private int id; 26 | private String name; 27 | 28 | 29 | } 30 | -------------------------------------------------------------------------------- /instructor/introduction/org/jetbrains/kotlinworkshop/introduction/_Shared/CustomerRepository.kt: -------------------------------------------------------------------------------- 1 | package org.jetbrains.kotlinworkshop.introduction._Shared 2 | 3 | import org.jetbrains.kotlinworkshop.introduction._11Generics.*; 4 | 5 | class CustomerRepository : Repository { 6 | override fun getById(id: Int): T { 7 | TODO("not implemented") //To change body of created functions use File | Settings | File Templates. 8 | } 9 | 10 | override fun getAll(): List { 11 | TODO("not implemented") //To change body of created functions use File | Settings | File Templates. 12 | } 13 | } -------------------------------------------------------------------------------- /instructor/quizzes/org/jetbrains/kotlinworkshop/quizzes/_1Intro/_1IntroTasks.kt: -------------------------------------------------------------------------------- 1 | package org.jetbrains.kotlinworkshop.quizzes._1Intro 2 | 3 | fun main() { 4 | var string = 1 5 | // the variable string has type Int 6 | // string = "a" 7 | 8 | val languages = listOf("Java") 9 | // list is read-only 10 | // languages.add("Kotlin") 11 | 12 | println(listOf('a', 'b', 'c').joinToString( 13 | separator = "", prefix = "(", postfix = ")")) 14 | // (abc) 15 | 16 | println("Kotlin" in "Java".."Scala") // true 17 | // "Java" <= "Kotlin" && "Kotlin" <= "Scala" 18 | 19 | println("Kotlin" in setOf("Java", "Scala")) // false 20 | 21 | val list = mutableListOf("Kotlin", "Java", "Scala") 22 | list.sort() 23 | println(list) 24 | 25 | for (c in '0' until '9') { 26 | print(c) 27 | } 28 | for (c in '0'..'8') { 29 | print(c) 30 | } 31 | // 012345678 32 | 33 | } -------------------------------------------------------------------------------- /instructor/quizzes/org/jetbrains/kotlinworkshop/quizzes/_1Intro/_2Foo.kt: -------------------------------------------------------------------------------- 1 | package org.jetbrains.kotlinworkshop.quizzes._1Intro 2 | 3 | val foo1 = run { 4 | println("Calculating foo...") 5 | "foo" 6 | } 7 | 8 | fun foo2(): String { 9 | println("Calculating foo...") 10 | return "foo" 11 | } 12 | 13 | fun main() { 14 | println("======") 15 | println("First ${foo1}, second ${foo1}") 16 | println("------") 17 | println("First ${foo2()}, second ${foo2()}") 18 | } -------------------------------------------------------------------------------- /instructor/quizzes/org/jetbrains/kotlinworkshop/quizzes/_2Extensions/Extensions.kt: -------------------------------------------------------------------------------- 1 | package org.jetbrains.kotlinworkshop.quizzes._2Extensions 2 | 3 | // Try 'convert receiver to parameter' 4 | // and 'convert parameter to receiver' actions 5 | fun List.sum(): Int { 6 | var result = 0 7 | for (i in this) { 8 | result += i 9 | } 10 | return result 11 | } 12 | 13 | fun main() { 14 | val sum = listOf(1, 2, 3).sum() 15 | println(sum) 16 | } -------------------------------------------------------------------------------- /instructor/quizzes/org/jetbrains/kotlinworkshop/quizzes/_2Extensions/MemberVsExtension.kt: -------------------------------------------------------------------------------- 1 | package org.jetbrains.kotlinworkshop.quizzes._2Extensions 2 | 3 | fun String.get(index: Int) = '*' 4 | 5 | fun main() { 6 | println("abc".get(1)) // b 7 | } 8 | -------------------------------------------------------------------------------- /instructor/quizzes/org/jetbrains/kotlinworkshop/quizzes/_2Extensions/ParentVsChild.kt: -------------------------------------------------------------------------------- 1 | package org.jetbrains.kotlinworkshop.quizzes._2Extensions 2 | 3 | open class Parent 4 | class Child: Parent() 5 | 6 | fun Parent.foo() = "parent" 7 | 8 | fun Child.foo() = "child" 9 | 10 | fun main() { 11 | val parent: Parent = Child() 12 | println(parent.foo()) 13 | } -------------------------------------------------------------------------------- /instructor/quizzes/org/jetbrains/kotlinworkshop/quizzes/_2Extensions/ParentVsChildJava.java: -------------------------------------------------------------------------------- 1 | package org.jetbrains.kotlinworkshop.quizzes._2Extensions; 2 | 3 | public class ParentVsChildJava { 4 | public static void main(String[] args) { 5 | Parent parent = new Child(); 6 | System.out.println(foo(parent)); 7 | System.out.println(ParentVsChildKt.foo(parent)); 8 | } 9 | 10 | private static String foo(Parent parent) { 11 | return "parent"; 12 | } 13 | 14 | private static String foo(Child child) { 15 | return "child"; 16 | } 17 | } 18 | -------------------------------------------------------------------------------- /instructor/quizzes/org/jetbrains/kotlinworkshop/quizzes/_2Extensions/RepeatExample.kt: -------------------------------------------------------------------------------- 1 | package org.jetbrains.kotlinworkshop.quizzes._2Extensions 2 | 3 | fun String.repeat(n: Int) = buildString { 4 | for (i in 1..n) { 5 | append(this@repeat) 6 | } 7 | } 8 | 9 | fun main() { 10 | println("ab".repeat(3)) // ababab 11 | } -------------------------------------------------------------------------------- /instructor/quizzes/org/jetbrains/kotlinworkshop/quizzes/_2Extensions/UsingRepeatFromJava.java: -------------------------------------------------------------------------------- 1 | package org.jetbrains.kotlinworkshop.quizzes._2Extensions; 2 | 3 | public class UsingRepeatFromJava { 4 | public static void main(String[] args) { 5 | System.out.println(RepeatExampleKt.repeat("ab", 3)); // ababab 6 | } 7 | } 8 | -------------------------------------------------------------------------------- /instructor/quizzes/org/jetbrains/kotlinworkshop/quizzes/_3Classes/Evaluation.kt: -------------------------------------------------------------------------------- 1 | package org.jetbrains.kotlinworkshop.quizzes._3Classes 2 | 3 | class TwoNumbers1(val first: Int, val second: Int) 4 | data class TwoNumbers2(val first: Int, val second: Int) 5 | 6 | fun test1() { 7 | val p1 = TwoNumbers1(1, 3) 8 | val p2 = TwoNumbers1(1, 3) 9 | println(p1 == p2) // false 10 | } 11 | 12 | fun test2() { 13 | val p1 = TwoNumbers2(1, 3) 14 | val p2 = TwoNumbers2(1, 3) 15 | println(p1 == p2) // true 16 | } 17 | 18 | fun main() { 19 | test1() 20 | test2() 21 | } 22 | -------------------------------------------------------------------------------- /instructor/quizzes/org/jetbrains/kotlinworkshop/quizzes/_3Classes/Foo.kt: -------------------------------------------------------------------------------- 1 | package org.jetbrains.kotlinworkshop.quizzes._3Classes 2 | 3 | val foo1 = run { 4 | println("Calculating the answer... (1)") 5 | 42 6 | } 7 | 8 | val foo2: Int 9 | get() { 10 | println("Calculating the answer... (2)") 11 | return 42 12 | } 13 | 14 | fun main() { 15 | println("foo1:") 16 | println(foo1) 17 | println(foo1) 18 | println("foo2:") 19 | println(foo2) 20 | println(foo2) 21 | } -------------------------------------------------------------------------------- /instructor/quizzes/org/jetbrains/kotlinworkshop/quizzes/_3Classes/InnerAndNested.kt: -------------------------------------------------------------------------------- 1 | package org.jetbrains.kotlinworkshop.quizzes._3Classes 2 | 3 | class Outer { 4 | class A { 5 | fun foo() { 6 | // this@Outer 7 | } 8 | } 9 | inner class B { 10 | fun foo() { 11 | this@Outer 12 | } 13 | } 14 | } -------------------------------------------------------------------------------- /instructor/quizzes/org/jetbrains/kotlinworkshop/quizzes/_3Classes/Person.kt: -------------------------------------------------------------------------------- 1 | package org.jetbrains.kotlinworkshop.quizzes._3Classes 2 | 3 | class Person(val name: String, var age: Int) -------------------------------------------------------------------------------- /instructor/quizzes/org/jetbrains/kotlinworkshop/quizzes/_3Classes/UsePersonFromJava.java: -------------------------------------------------------------------------------- 1 | package org.jetbrains.kotlinworkshop.quizzes._3Classes; 2 | 3 | public class UsePersonFromJava { 4 | public static void main(String[] args) { 5 | // constructor 6 | Person person = new Person("Alice", 27); 7 | 8 | // 2 getters 9 | System.out.println(person.getName()); 10 | System.out.println(person.getAge()); 11 | 12 | // 1 setter 13 | person.setAge(28); 14 | } 15 | } 16 | -------------------------------------------------------------------------------- /instructor/quizzes/org/jetbrains/kotlinworkshop/quizzes/_3Classes/Visibility.kt: -------------------------------------------------------------------------------- 1 | package org.jetbrains.kotlinworkshop.quizzes._3Classes 2 | 3 | fun main() { 4 | foo() 5 | // C().bar() 6 | } 7 | 8 | private fun foo() {} 9 | 10 | class C { 11 | private fun bar() {} 12 | 13 | inner class A { 14 | fun foo() = bar() 15 | } 16 | } -------------------------------------------------------------------------------- /instructor/quizzes/org/jetbrains/kotlinworkshop/quizzes/_4Nullability/Lists.kt: -------------------------------------------------------------------------------- 1 | package org.jetbrains.kotlinworkshop.quizzes._4Nullability 2 | 3 | fun foo(list1: List, list2: List?) { 4 | list1.size 5 | list2?.size 6 | 7 | val i: Int? = list1.get(0) 8 | val j: Int? = list2?.get(0) 9 | } 10 | -------------------------------------------------------------------------------- /instructor/quizzes/org/jetbrains/kotlinworkshop/quizzes/_4Nullability/Name.kt: -------------------------------------------------------------------------------- 1 | package org.jetbrains.kotlinworkshop.quizzes._4Nullability 2 | 3 | class Name(val value: String?) 4 | 5 | fun isFoo1(n: Name) = n.value == "foo" 6 | //fun isFoo2(n: Name?) = n.value == "foo" 7 | fun isFoo3(n: Name?) = n != null && n.value == "foo" 8 | fun isFoo4(n: Name?) = n?.value == "foo" 9 | 10 | fun main() { 11 | // isFoo1(null) 12 | // isFoo2(null) 13 | isFoo3(null) 14 | isFoo4(null) 15 | } 16 | -------------------------------------------------------------------------------- /instructor/quizzes/org/jetbrains/kotlinworkshop/quizzes/_4Nullability/SafeCasts.kt: -------------------------------------------------------------------------------- 1 | package org.jetbrains.kotlinworkshop.quizzes._4Nullability 2 | 3 | fun main() { 4 | val s = "abc" 5 | println(s as Int?) 6 | println(s as? Int) 7 | } -------------------------------------------------------------------------------- /instructor/quizzes/org/jetbrains/kotlinworkshop/quizzes/_4Nullability/isNullOrEmpty.kt: -------------------------------------------------------------------------------- 1 | package org.jetbrains.kotlinworkshop.quizzes._4Nullability 2 | 3 | fun main() { 4 | val s1: String? = null 5 | val s2: String? = "" 6 | println(s1.isNullOrEmpty() && s2.isNullOrEmpty()) 7 | } 8 | 9 | fun String?.isNullOrEmpty(): Boolean = this == null || this.isEmpty() -------------------------------------------------------------------------------- /instructor/quizzes/org/jetbrains/kotlinworkshop/quizzes/_5TypeSystem/JavaClass.java: -------------------------------------------------------------------------------- 1 | package org.jetbrains.kotlinworkshop.quizzes._5TypeSystem; 2 | 3 | import java.util.List; 4 | 5 | public class JavaClass { 6 | public String getValue() { 7 | return null; 8 | } 9 | 10 | public static void dangerousJavaMethod(List list) { 11 | list.add(null); 12 | } 13 | } 14 | -------------------------------------------------------------------------------- /instructor/quizzes/org/jetbrains/kotlinworkshop/quizzes/_5TypeSystem/Parent.java: -------------------------------------------------------------------------------- 1 | package org.jetbrains.kotlinworkshop.quizzes._5TypeSystem; 2 | 3 | public class Parent { 4 | public Parent() { 5 | 6 | getFoo().length(); 7 | } 8 | 9 | String getFoo() { 10 | return ""; 11 | } 12 | } 13 | -------------------------------------------------------------------------------- /instructor/quizzes/org/jetbrains/kotlinworkshop/quizzes/_5TypeSystem/Subclass.java: -------------------------------------------------------------------------------- 1 | package org.jetbrains.kotlinworkshop.quizzes._5TypeSystem; 2 | 3 | public class Subclass extends Parent { 4 | private String foo; 5 | 6 | public Subclass(String foo) { 7 | this.foo = foo; 8 | } 9 | 10 | @Override 11 | String getFoo() { 12 | return foo; 13 | } 14 | } 15 | -------------------------------------------------------------------------------- /instructor/quizzes/org/jetbrains/kotlinworkshop/quizzes/_5TypeSystem/Usage.java: -------------------------------------------------------------------------------- 1 | package org.jetbrains.kotlinworkshop.quizzes._5TypeSystem; 2 | 3 | public class Usage { 4 | public static void main(String[] args) { 5 | Subclass subclass = new Subclass(""); 6 | } 7 | } 8 | -------------------------------------------------------------------------------- /instructor/quizzes/org/jetbrains/kotlinworkshop/quizzes/_5TypeSystem/_1NPE.kt: -------------------------------------------------------------------------------- 1 | package org.jetbrains.kotlinworkshop.quizzes._5TypeSystem 2 | 3 | fun mightThrowNPE() { 4 | println(JavaClass().value.length) 5 | } 6 | 7 | fun main() { 8 | mightThrowNPE() // throws NPE, because getValue() returns null 9 | } -------------------------------------------------------------------------------- /instructor/quizzes/org/jetbrains/kotlinworkshop/quizzes/_5TypeSystem/_2ExplicitTypeSpecification.kt: -------------------------------------------------------------------------------- 1 | package org.jetbrains.kotlinworkshop.quizzes._5TypeSystem 2 | 3 | fun explicitType() { 4 | val value: String = JavaClass().value // IllegalStateException: JavaClass().value must not be null 5 | println(value.length) 6 | } 7 | 8 | fun main() { 9 | explicitType() 10 | } -------------------------------------------------------------------------------- /instructor/quizzes/org/jetbrains/kotlinworkshop/quizzes/_5TypeSystem/_2NullInList.kt: -------------------------------------------------------------------------------- 1 | package org.jetbrains.kotlinworkshop.quizzes._5TypeSystem 2 | 3 | import org.jetbrains.kotlinworkshop.quizzes._5TypeSystem.JavaClass.dangerousJavaMethod 4 | 5 | fun mightContainNull(): List { 6 | val list: List = arrayListOf(1, 2, 3) 7 | // change the implementation of the `dangerousJavaMethod` 8 | // so that it add `null` values in the list 9 | dangerousJavaMethod(list) 10 | return list 11 | } 12 | 13 | fun main() { 14 | for (i in mightContainNull()) { // NPE 15 | println(i) 16 | } 17 | } -------------------------------------------------------------------------------- /instructor/quizzes/org/jetbrains/kotlinworkshop/quizzes/_5TypeSystem/_3NPEDuringInitialization.kt: -------------------------------------------------------------------------------- 1 | package org.jetbrains.kotlinworkshop.quizzes._5TypeSystem 2 | 3 | open class A(open val value: String) { 4 | init { 5 | 6 | } 7 | } 8 | 9 | class B(override val value: String) : A(value) 10 | 11 | fun main() { 12 | // Complete the declaration of the class A 13 | // so that NPE is thrown during the creation of its subclass B instance 14 | B("a") 15 | } -------------------------------------------------------------------------------- /instructor/quizzes/org/jetbrains/kotlinworkshop/quizzes/_6Lambdas/Heroes.kt: -------------------------------------------------------------------------------- 1 | package org.jetbrains.kotlinworkshop.quizzes._6Lambdas 2 | 3 | import org.jetbrains.kotlinworkshop.quizzes._6Lambdas.Gender.FEMALE 4 | import org.jetbrains.kotlinworkshop.quizzes._6Lambdas.Gender.MALE 5 | 6 | class Hero(val name: String, val age: Int, val gender: Gender?) 7 | enum class Gender { MALE, FEMALE } 8 | 9 | fun main() { 10 | val heroes = listOf( 11 | Hero("The Captain", 60, MALE), 12 | Hero("Frenchy", 42, MALE), 13 | Hero("The Kid", 9, null), 14 | Hero("Lady Lauren", 29, FEMALE), 15 | Hero("First Mate", 29, MALE), 16 | Hero("Sir Stephen", 37, MALE)) 17 | 18 | println(heroes.last().name) 19 | 20 | println(heroes.firstOrNull { it.age == 30 }?.name) 21 | println(heroes.last { it.age == 29 }.name) 22 | 23 | println(heroes.map { it.age }.distinct().size) 24 | println(heroes.filter { it.age < 30 }.size) 25 | 26 | val (youngest, oldest) = heroes.partition { it.age < 30 } 27 | println(oldest.size) 28 | println(youngest.size) 29 | 30 | println(heroes.maxBy { it.age }?.name) 31 | 32 | println(heroes.all { it.age < 50 }) 33 | println(heroes.any { it.gender == FEMALE }) 34 | 35 | 36 | val mapByAge: Map> = heroes.groupBy { it.age } 37 | val (age, group) = mapByAge.maxBy { (_, group) -> group.size }!! 38 | println(age) 39 | println(group.size) 40 | 41 | val mapByName: Map = heroes.associateBy { it.name } 42 | println(mapByName["Frenchy"]?.age) 43 | println(mapByName.getValue("Frenchy").age) 44 | println(mapByName["unknown"]) 45 | 46 | val unknownHero = Hero("Unknown", 0, null) 47 | println(mapByName.getOrElse("unknown") { unknownHero }.age) 48 | 49 | val (first, second) = heroes 50 | .flatMap { heroes.map { hero -> it to hero } } 51 | .maxBy { it.first.age - it.second.age }!! 52 | println(first.name) 53 | println(second.name) 54 | } -------------------------------------------------------------------------------- /instructor/quizzes/org/jetbrains/kotlinworkshop/quizzes/_7InlineAndLazyIteration/Inline.kt: -------------------------------------------------------------------------------- 1 | package org.jetbrains.kotlinworkshop.quizzes._7InlineAndLazyIteration 2 | 3 | fun main() { 4 | 5 | val list = listOf(1, 2, 3) 6 | val result = list.filter { it > 0 } 7 | 8 | 9 | } 10 | 11 | inline fun List.filter(predicate: (T) -> Boolean): List { 12 | val destination = ArrayList() 13 | for (element in this) { 14 | if (predicate(element)) { 15 | destination.add(element) 16 | } 17 | } 18 | return destination 19 | } -------------------------------------------------------------------------------- /instructor/quizzes/org/jetbrains/kotlinworkshop/quizzes/_7InlineAndLazyIteration/IntermediateCollections.kt: -------------------------------------------------------------------------------- 1 | package org.jetbrains.kotlinworkshop.quizzes._7InlineAndLazyIteration 2 | 3 | fun main() { 4 | collectionExample() 5 | println() 6 | sequenceExample() 7 | } 8 | 9 | fun collectionExample() { 10 | val list = listOf(1, 2, -3) 11 | val mapResult = list.map { it * it } 12 | println(mapResult) 13 | val filterResult = mapResult.filter { it % 2 == 1 } 14 | println(filterResult) 15 | val maxOddSquare = filterResult.max() 16 | println(maxOddSquare) 17 | } 18 | 19 | fun sequenceExample() { 20 | val sequence = listOf(1, 2, -3).asSequence() 21 | val mapResult = sequence.map { it * it } 22 | println(mapResult) 23 | val filterResult = mapResult.filter { it % 2 == 1 } 24 | println(filterResult) 25 | val maxOddSquare = filterResult.max() 26 | println(maxOddSquare) 27 | } -------------------------------------------------------------------------------- /instructor/quizzes/org/jetbrains/kotlinworkshop/quizzes/_7InlineAndLazyIteration/LazyIteration.kt: -------------------------------------------------------------------------------- 1 | package org.jetbrains.kotlinworkshop.quizzes._7InlineAndLazyIteration 2 | 3 | // Eager and lazy evaluation 4 | 5 | fun m(i: Int): Int { 6 | print("m$i ") 7 | return i * i 8 | } 9 | 10 | fun f(i: Int): Boolean { 11 | print("f$i ") 12 | return i % 2 == 0 13 | } 14 | 15 | fun main() { 16 | val list = listOf(1, 2, 3, 4) 17 | 18 | list.map(::m).filter(::f) 19 | 20 | println() 21 | 22 | list.asSequence().map(::m).filter(::f).toList() 23 | 24 | println() 25 | 26 | list.asSequence().map(::m).filter(::f) 27 | 28 | println() 29 | 30 | list.asSequence().filter(::f).map(::m).toList() 31 | 32 | } -------------------------------------------------------------------------------- /jetbrainslogo.png: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/Kotlin/workshop/37552440e6e6a1f7607ea5722eef1e8d5578d4f5/jetbrainslogo.png -------------------------------------------------------------------------------- /kotlinlogo.png: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/Kotlin/workshop/37552440e6e6a1f7607ea5722eef1e8d5578d4f5/kotlinlogo.png -------------------------------------------------------------------------------- /settings.gradle: -------------------------------------------------------------------------------- 1 | rootProject.name = 'kotlin-workshop' -------------------------------------------------------------------------------- /student/tasks/org/jetbrains/kotlinworkshop/student/single/_0Nullability/MessageUtil.java: -------------------------------------------------------------------------------- 1 | package org.jetbrains.kotlinworkshop.student.single._0Nullability; 2 | 3 | import org.jetbrains.annotations.NotNull; 4 | import org.jetbrains.annotations.Nullable; 5 | 6 | public class MessageUtil { 7 | public static void sendMessageToClient(@Nullable Client client, @Nullable String message, @NotNull Mailer mailer) { 8 | if (client == null || message == null) return; 9 | 10 | PersonalInfo personalInfo = client.getPersonalInfo(); 11 | if (personalInfo == null) return; 12 | 13 | String email = personalInfo.getEmail(); 14 | if (email == null) return; 15 | 16 | mailer.sendMessage(email, message); 17 | } 18 | } 19 | -------------------------------------------------------------------------------- /student/tasks/org/jetbrains/kotlinworkshop/student/single/_0Nullability/Task.kt: -------------------------------------------------------------------------------- 1 | package org.jetbrains.kotlinworkshop.student.single._0Nullability 2 | 3 | class Client(val personalInfo: PersonalInfo?) 4 | class PersonalInfo(val email: String?) 5 | 6 | interface Mailer { 7 | fun sendMessage(email: String, message: String) 8 | } 9 | 10 | /* 11 | Rewrite Java method 'MessageUtil.sendMessageToClient' in Kotlin in 2-3 lines. 12 | */ 13 | fun sendMessageToClient(client: Client?, message: String?, mailer: Mailer) { 14 | TODO() 15 | } -------------------------------------------------------------------------------- /student/tasks/org/jetbrains/kotlinworkshop/student/single/_1BreakingSafety/JavaClass.java: -------------------------------------------------------------------------------- 1 | package org.jetbrains.kotlinworkshop.student.single._1BreakingSafety; 2 | 3 | import sun.reflect.generics.reflectiveObjects.NotImplementedException; 4 | 5 | import java.util.List; 6 | 7 | public class JavaClass { 8 | public String getValue() { 9 | throw new NotImplementedException(); 10 | } 11 | 12 | public static void dangerousJavaMethod(List list) { 13 | throw new NotImplementedException(); 14 | } 15 | } 16 | -------------------------------------------------------------------------------- /student/tasks/org/jetbrains/kotlinworkshop/student/single/_1BreakingSafety/_1NPE.kt: -------------------------------------------------------------------------------- 1 | package org.jetbrains.kotlinworkshop.student.single._1BreakingSafety 2 | 3 | 4 | fun mightThrowNPE() { 5 | // change 'JavaClass.getValue' to make the call below throw NPE 6 | println(JavaClass().value.length) 7 | } -------------------------------------------------------------------------------- /student/tasks/org/jetbrains/kotlinworkshop/student/single/_1BreakingSafety/_2NullInList.kt: -------------------------------------------------------------------------------- 1 | package org.jetbrains.kotlinworkshop.student.single._1BreakingSafety 2 | 3 | import org.jetbrains.kotlinworkshop.student.single._1BreakingSafety.JavaClass.* 4 | 5 | 6 | fun mightContainNull(): List { 7 | val list: List = arrayListOf(1, 2, 3) 8 | // try to add 'null' value to the list of int's in 'dangerousJavaMethod' 9 | dangerousJavaMethod(list) 10 | return list 11 | } -------------------------------------------------------------------------------- /student/tasks/org/jetbrains/kotlinworkshop/student/single/_1BreakingSafety/_3NotImmutableProperty.kt: -------------------------------------------------------------------------------- 1 | package org.jetbrains.kotlinworkshop.student.single._1BreakingSafety 2 | 3 | class MyClass { 4 | // Change the implementation of 'myProperty' to make it return different values each time. 5 | // You may add additional properties if you need. 6 | val myProperty: Int = TODO() 7 | } -------------------------------------------------------------------------------- /student/tasks/org/jetbrains/kotlinworkshop/student/single/_1BreakingSafety/_4NPEDuringInitialization.kt: -------------------------------------------------------------------------------- 1 | package org.jetbrains.kotlinworkshop.student.single._1BreakingSafety 2 | 3 | /* optional task */ 4 | 5 | open class A(open val value: String) { 6 | 7 | } 8 | 9 | class B(override val value: String) : A(value) 10 | 11 | fun main() { 12 | // Complete the declaration of the class A 13 | // so that NPE is thrown during the creation of its subclass B instance 14 | B("a") 15 | } -------------------------------------------------------------------------------- /student/tasks/org/jetbrains/kotlinworkshop/student/single/_2Shop/JavaCode.java: -------------------------------------------------------------------------------- 1 | package org.jetbrains.kotlinworkshop.student.single._2Shop; 2 | 3 | import java.util.*; 4 | 5 | public class JavaCode { 6 | public Collection doSomethingStrangeWithCollection(Collection collection) { 7 | Map> groupsByLength = new HashMap>(); 8 | for (String s : collection) { 9 | List strings = groupsByLength.get(s.length()); 10 | if (strings == null) { 11 | strings = new ArrayList(); 12 | groupsByLength.put(s.length(), strings); 13 | } 14 | strings.add(s); 15 | } 16 | 17 | int maximumSizeOfGroup = 0; 18 | for (List group : groupsByLength.values()) { 19 | if (group.size() > maximumSizeOfGroup) { 20 | maximumSizeOfGroup = group.size(); 21 | } 22 | } 23 | 24 | for (List group : groupsByLength.values()) { 25 | if (group.size() == maximumSizeOfGroup) { 26 | return group; 27 | } 28 | } 29 | return null; 30 | } 31 | } 32 | -------------------------------------------------------------------------------- /student/tasks/org/jetbrains/kotlinworkshop/student/single/_2Shop/_10GroupBy.kt: -------------------------------------------------------------------------------- 1 | package org.jetbrains.kotlinworkshop.student.single._2Shop 2 | 3 | fun main() { 4 | 5 | val result = listOf("a", "b", "ba", "ccc", "ad").groupBy { it.length } 6 | 7 | result == mapOf(1 to listOf("a", "b"), 2 to listOf("ba", "ad"), 3 to listOf("ccc")) 8 | 9 | println(result) // {1=[a, b], 2=[ba, ad], 3=[ccc]} 10 | } 11 | 12 | // Return a map of the customers living in each city 13 | fun Shop.groupCustomersByCity(): Map> { 14 | TODO() 15 | } 16 | -------------------------------------------------------------------------------- /student/tasks/org/jetbrains/kotlinworkshop/student/single/_2Shop/_11Partition.kt: -------------------------------------------------------------------------------- 1 | package org.jetbrains.kotlinworkshop.student.single._2Shop 2 | 3 | fun main() { 4 | val numbers = listOf(1, 3, -4, 2, -11) 5 | 6 | val (positive, negative) = numbers.partition { it > 0 } 7 | 8 | positive == listOf(1, 3, 2) 9 | negative == listOf(-4, -11) 10 | } 11 | 12 | // Return customers who have more undelivered orders than delivered 13 | fun Shop.getCustomersWithMoreUndeliveredOrdersThanDelivered(): Set { 14 | TODO() 15 | } 16 | -------------------------------------------------------------------------------- /student/tasks/org/jetbrains/kotlinworkshop/student/single/_2Shop/_12Fold.kt: -------------------------------------------------------------------------------- 1 | package org.jetbrains.kotlinworkshop.student.single._2Shop 2 | 3 | fun main() { 4 | val result = listOf(1, 2, 3, 4).fold(1, { partResult, element -> element * partResult }) 5 | println(result) // 24 = 1 * 2 * 3 * 4 6 | } 7 | 8 | // The same as 9 | fun whatFoldDoes(): Int { 10 | var result = 1 11 | listOf(1, 2, 3, 4).forEach { element -> result *= element } 12 | return result 13 | } 14 | 15 | // Return the set of products ordered by every customer 16 | fun Shop.getSetOfProductsOrderedByEveryCustomer(): Set { 17 | return customers.fold(allOrderedProducts, { 18 | orderedByAll, customer -> 19 | TODO() 20 | }) 21 | } 22 | -------------------------------------------------------------------------------- /student/tasks/org/jetbrains/kotlinworkshop/student/single/_2Shop/_13CompoundTasks.kt: -------------------------------------------------------------------------------- 1 | package org.jetbrains.kotlinworkshop.student.single._2Shop 2 | 3 | // Return the set of customers who ordered the specified product 4 | fun Shop.getCustomersWhoOrderedProduct(product: Product): Set { 5 | TODO() 6 | } 7 | 8 | // Return the most expensive product among all delivered products 9 | // (use the Order.isDelivered flag) 10 | fun Customer.getMostExpensiveDeliveredProduct(): Product? { 11 | TODO() 12 | } 13 | 14 | // Return the number of times the given product was ordered. 15 | // Note: a customer may order the same product for several times. 16 | fun Shop.getNumberOfTimesProductWasOrdered(product: Product): Int { 17 | TODO() 18 | } 19 | -------------------------------------------------------------------------------- /student/tasks/org/jetbrains/kotlinworkshop/student/single/_2Shop/_14SmthWithCollections.kt: -------------------------------------------------------------------------------- 1 | package org.jetbrains.kotlinworkshop.student.single._2Shop 2 | 3 | // Rewrite JavaCode.doSomethingStrangeWithCollection function to Kotlin. 4 | fun doSomethingStrangeWithCollection(collection: Collection): Collection? { 5 | 6 | val groupsByLength = collection.groupBy { s -> TODO() } 7 | 8 | return groupsByLength.values.maxBy { group -> TODO() } 9 | } 10 | 11 | -------------------------------------------------------------------------------- /student/tasks/org/jetbrains/kotlinworkshop/student/single/_2Shop/_1Introduction.kt: -------------------------------------------------------------------------------- 1 | package org.jetbrains.kotlinworkshop.student.single._2Shop 2 | 3 | import org.jetbrains.kotlinworkshop.student.single._2Shop.* 4 | import java.util.* 5 | 6 | /* 7 | * This part of workshop was inspired by: 8 | * https://github.com/goldmansachs/gs-collections-kata 9 | */ 10 | 11 | /* 12 | * There are many operations that help to transform one collection into another, starting with 'to' 13 | */ 14 | fun main() { 15 | val list = listOf(2, 2, 1) 16 | val set = list.toSet() 17 | println(set) // [2, 1] 18 | 19 | val sortedSet = list.toCollection(TreeSet()) 20 | println(sortedSet) // [1, 2] 21 | } 22 | 23 | // Return a set containing all the customers of this shop 24 | fun Shop.getSetOfCustomers(): Set { 25 | TODO() 26 | // return this.customers 27 | } 28 | 29 | -------------------------------------------------------------------------------- /student/tasks/org/jetbrains/kotlinworkshop/student/single/_2Shop/_2FilterMap.kt: -------------------------------------------------------------------------------- 1 | package org.jetbrains.kotlinworkshop.student.single._2Shop 2 | 3 | fun main() { 4 | val list = listOf(-1, 3, 0, -5, 7) 5 | 6 | // If a lambda has exactly one parameter, that parameter can be accessed as 'it' 7 | val positiveNumbers = list.filter { it > 0 } 8 | println(positiveNumbers) // [3, 7] 9 | 10 | val squares = list.map { it * it } 11 | println(squares) // [1, 9, 0, 25, 49] 12 | } 13 | 14 | // Return the set of cities the customers are from 15 | fun Shop.getCitiesCustomersAreFrom(): Set { 16 | TODO() 17 | } 18 | 19 | // Return a list of the customers who live in the given city 20 | fun Shop.getCustomersFrom(city: City): List { 21 | TODO() 22 | } 23 | 24 | 25 | -------------------------------------------------------------------------------- /student/tasks/org/jetbrains/kotlinworkshop/student/single/_2Shop/_3AllAnyAndOtherPredicates.kt: -------------------------------------------------------------------------------- 1 | package org.jetbrains.kotlinworkshop.student.single._2Shop 2 | 3 | fun main() { 4 | val list = listOf(-1, 3, 0, -5, 7) 5 | 6 | val isZero: (Int) -> Boolean = { it == 0 } 7 | 8 | val hasZero: Boolean = list.any(isZero) 9 | println(hasZero) // true 10 | 11 | val allZeros: Boolean = list.all(isZero) 12 | println(allZeros) // false 13 | 14 | val numberOfZeros: Int = list.count(isZero) 15 | println(numberOfZeros) // 1 16 | 17 | val firstPositiveNumber: Int? = list.firstOrNull { it > 0 } 18 | println(firstPositiveNumber) // 3 19 | } 20 | 21 | // Return true if the customer is from the given city 22 | fun Customer.isFrom(city: City): Boolean { 23 | TODO() 24 | } 25 | 26 | // Return true if all customers are from the given city 27 | fun Shop.checkAllCustomersAreFrom(city: City): Boolean { 28 | TODO() 29 | } 30 | 31 | // Return true if there is at least one customer from the given city 32 | fun Shop.hasCustomerFrom(city: City): Boolean { 33 | TODO() 34 | } 35 | 36 | // Return the number of customers from the given city 37 | fun Shop.countCustomersFrom(city: City): Int { 38 | TODO() 39 | } 40 | 41 | // Return a customer who lives in the given city, or null if there is none 42 | fun Shop.findAnyCustomerFrom(city: City): Customer? { 43 | TODO() 44 | } -------------------------------------------------------------------------------- /student/tasks/org/jetbrains/kotlinworkshop/student/single/_2Shop/_4FlatMap.kt: -------------------------------------------------------------------------------- 1 | package org.jetbrains.kotlinworkshop.student.single._2Shop 2 | 3 | fun main() { 4 | val result = listOf("abc", "12").flatMap(String::toList) 5 | 6 | result == listOf('a', 'b', 'c', '1', '2') 7 | 8 | println(result) // [a, b, c, 1, 2] 9 | } 10 | 11 | // Return all products that were ordered by customer 12 | val Customer.orderedProducts: Set get() { 13 | TODO() 14 | } 15 | 16 | // Return all products that were ordered by at least one customer 17 | val Shop.allOrderedProducts: Set get() { 18 | TODO() 19 | } 20 | -------------------------------------------------------------------------------- /student/tasks/org/jetbrains/kotlinworkshop/student/single/_2Shop/_5MaxMin.kt: -------------------------------------------------------------------------------- 1 | package org.jetbrains.kotlinworkshop.student.single._2Shop 2 | 3 | fun main() { 4 | val max = listOf(1, 42, 4).max() 5 | val longestString = listOf("a", "ab", "b").maxBy { it.length } 6 | 7 | println(max) // 42 8 | println(longestString) // ab 9 | } 10 | 11 | // Return a customer whose order count is the highest among all customers 12 | fun Shop.getCustomerWithMaximumNumberOfOrders(): Customer? { 13 | TODO() 14 | } 15 | 16 | // Return the most expensive product which has been ordered 17 | fun Customer.getMostExpensiveOrderedProduct(): Product? { 18 | TODO() 19 | } 20 | -------------------------------------------------------------------------------- /student/tasks/org/jetbrains/kotlinworkshop/student/single/_2Shop/_6Sort.kt: -------------------------------------------------------------------------------- 1 | package org.jetbrains.kotlinworkshop.student.single._2Shop 2 | 3 | fun main() { 4 | val result = listOf("a", "bbb", "cc").sortedBy { it.length } 5 | 6 | println(result) // [a, cc, bbb] 7 | } 8 | 9 | // Return a list of customers, sorted by the ascending number of orders they made 10 | fun Shop.getCustomersSortedByNumberOfOrders(): List { 11 | TODO() 12 | } 13 | -------------------------------------------------------------------------------- /student/tasks/org/jetbrains/kotlinworkshop/student/single/_2Shop/_7Sum.kt: -------------------------------------------------------------------------------- 1 | package org.jetbrains.kotlinworkshop.student.single._2Shop 2 | 3 | fun main() { 4 | val sum = listOf(1, 5, 3).sum() 5 | 6 | println(sum) // 9 7 | } 8 | 9 | // Return the sum of prices of all products that a customer has ordered. 10 | // Note: a customer may order the same product for several times. 11 | fun Customer.getTotalOrderPrice(): Double { 12 | TODO() 13 | } 14 | -------------------------------------------------------------------------------- /student/tasks/org/jetbrains/kotlinworkshop/student/single/_2Shop/_8Zip.kt: -------------------------------------------------------------------------------- 1 | package org.jetbrains.kotlinworkshop.student.single._2Shop 2 | 3 | fun main() { 4 | 5 | val listOfPairs = "abCDa".zip("79371") 6 | 7 | println(listOfPairs) // [(a, 7), (b, 9), (C, 3), (D, 7), (a, 1)] 8 | } 9 | 10 | // Find the correspondence between customers and their names (as a list or pairs) 11 | fun Shop.zipNameAndCustomer(): List> { 12 | TODO() 13 | } -------------------------------------------------------------------------------- /student/tasks/org/jetbrains/kotlinworkshop/student/single/_2Shop/_9AssociateBy.kt: -------------------------------------------------------------------------------- 1 | package org.jetbrains.kotlinworkshop.student.single._2Shop 2 | 3 | fun main() { 4 | val list = listOf("a", "bc", "bd") 5 | 6 | val map: Map = list.associateBy(String::hashCode) 7 | 8 | println(map) // {97=a, 3137=bc, 3138=bd} 9 | 10 | val noGrouping = list.associateBy(String::length) 11 | 12 | println(noGrouping) // {1=a, 2=bd} 13 | } 14 | 15 | // Find the correspondence between customers and their names (as a map) 16 | fun Shop.associateCustomersByName(): Map { 17 | TODO() 18 | } -------------------------------------------------------------------------------- /student/tasks/org/jetbrains/kotlinworkshop/student/single/_2Shop/shop.kt: -------------------------------------------------------------------------------- 1 | package org.jetbrains.kotlinworkshop.student.single._2Shop 2 | 3 | data class Shop(val name: String, val customers: List) 4 | 5 | data class Customer(val name: String, val city: City, val orders: List) { 6 | override fun toString() = "$name from ${city.name}" 7 | } 8 | 9 | data class Order(val products: List, val isDelivered: Boolean) 10 | 11 | data class Product(val name: String, val price: Double) { 12 | override fun toString() = "'$name' for $price" 13 | } 14 | 15 | data class City(val name: String) { 16 | override fun toString() = name 17 | } 18 | 19 | 20 | -------------------------------------------------------------------------------- /student/tasks/org/jetbrains/kotlinworkshop/student/single/_3HtmlBuilders/Task.kt: -------------------------------------------------------------------------------- 1 | package org.jetbrains.kotlinworkshop.student.single._3HtmlBuilders 2 | 3 | fun getTitleColor() = "#b9c9fe" 4 | fun getCellColor(row: Int, column: Int) = if ((row + column) % 2 == 0) "#dce4ff" else "#eff2ff" 5 | 6 | /* 7 | 1) Fill the table with the proper values from products. 8 | 2) Color the table like a chess board (using getTitleColor() and getCellColor() functions above). 9 | Pass a color as an argument to functions 'tr', 'td'. 10 | You can run the 'Html Demo' configuration in IntelliJ IDEA to see the rendered table. 11 | */ 12 | 13 | fun renderProductTable(): String { 14 | return html { 15 | table { 16 | tr { 17 | td { 18 | text("Product") 19 | } 20 | td { 21 | text("Price") 22 | } 23 | td { 24 | text("Popularity") 25 | } 26 | } 27 | val products = getProducts() 28 | 29 | } 30 | }.toString() 31 | } -------------------------------------------------------------------------------- /student/tasks/org/jetbrains/kotlinworkshop/student/single/_3HtmlBuilders/data.kt: -------------------------------------------------------------------------------- 1 | package org.jetbrains.kotlinworkshop.student.single._3HtmlBuilders 2 | 3 | data class Product(val description: String, val price: Double, val popularity: Int) 4 | 5 | val cactus = Product("cactus", 11.2, 13) 6 | val cake = Product("cake", 3.2, 111) 7 | val camera = Product("camera", 134.5, 2) 8 | val car = Product("car", 30000.0, 0) 9 | val carrot = Product("carrot", 1.34, 5) 10 | val cellPhone = Product("cell phone", 129.9, 99) 11 | val chimney = Product("chimney", 190.0, 2) 12 | val certificate = Product("certificate", 99.9, 1) 13 | val cigar = Product("cigar", 8.0, 51) 14 | val coffee = Product("coffee", 8.0, 67) 15 | val coffeeMaker = Product("coffee maker", 201.2, 1) 16 | val cola = Product("cola", 4.0, 67) 17 | val cranberry = Product("cranberry", 4.1, 39) 18 | val crocs = Product("crocs", 18.7, 10) 19 | val crocodile = Product("crocodile", 20000.2, 1) 20 | val cushion = Product("cushion", 131.0, 0) 21 | 22 | fun getProducts() = listOf(cactus, cake, camera, car, carrot, cellPhone, chimney, certificate, cigar, coffee, coffeeMaker, 23 | cola, cranberry, crocs, crocodile, cushion) -------------------------------------------------------------------------------- /student/tasks/org/jetbrains/kotlinworkshop/student/single/_3HtmlBuilders/html.kt: -------------------------------------------------------------------------------- 1 | package org.jetbrains.kotlinworkshop.student.single._3HtmlBuilders 2 | 3 | import java.util.* 4 | 5 | @DslMarker 6 | annotation class HtmlTagMarker 7 | 8 | @HtmlTagMarker 9 | open class Tag(val name: String) { 10 | val children: MutableList = ArrayList() 11 | val attributes: MutableList = ArrayList() 12 | 13 | override fun toString(): String { 14 | return "<$name" + 15 | (if (attributes.isEmpty()) "" else attributes.joinToString(separator = " ", prefix = " ")) + ">" + 16 | (if (children.isEmpty()) "" else children.joinToString(separator = "")) + 17 | "" 18 | } 19 | } 20 | 21 | class Attribute(val name: String, val value: String) { 22 | override fun toString() = """$name="$value"""" 23 | } 24 | 25 | fun T.set(name: String, value: String?): T { 26 | if (value != null) { 27 | attributes.add(Attribute(name, value)) 28 | } 29 | return this 30 | } 31 | 32 | fun Tag.doInit(tag: T, init: T.() -> Unit): T { 33 | tag.init() 34 | children.add(tag) 35 | return tag 36 | } 37 | 38 | class Html : Tag("html") 39 | class Table : Tag("table") 40 | class Center : Tag("center") 41 | class TR : Tag("tr") 42 | class TD : Tag("td") 43 | class Text(val text: String) : Tag("b") { 44 | override fun toString() = text 45 | } 46 | 47 | fun html(init: Html.() -> Unit): Html = Html().apply(init) 48 | 49 | fun Html.table(init: Table.() -> Unit) = doInit(Table(), init) 50 | fun Html.center(init: Center.() -> Unit) = doInit(Center(), init) 51 | 52 | fun Table.tr(color: String? = null, init: TR.() -> Unit) = doInit(TR(), init).set("bgcolor", color) 53 | 54 | fun TR.td(color: String? = null, align: String = "left", init: TD.() -> Unit) = doInit(TD(), init).set("align", align).set("bgcolor", color) 55 | 56 | fun Tag.text(s: Any?) = doInit(Text(s.toString()), {}) 57 | 58 | -------------------------------------------------------------------------------- /student/tasks/org/jetbrains/kotlinworkshop/student/single/_3HtmlBuilders/htmlDemo.kt: -------------------------------------------------------------------------------- 1 | package org.jetbrains.kotlinworkshop.student.single._3HtmlBuilders 2 | 3 | import javax.swing.* 4 | import javax.swing.SwingConstants.* 5 | 6 | fun main() { 7 | with(JFrame("Product popularity")) { 8 | setSize(600, 600) 9 | defaultCloseOperation = JFrame.EXIT_ON_CLOSE 10 | add(JScrollPane(JLabel(renderProductTable(), CENTER))) 11 | isVisible = true 12 | } 13 | } 14 | 15 | -------------------------------------------------------------------------------- /student/tasks/org/jetbrains/kotlinworkshop/student/single/_3TaxiPark/TaxiPark.kt: -------------------------------------------------------------------------------- 1 | package org.jetbrains.kotlinworkshop.student.single._3TaxiPark 2 | 3 | class TaxiPark( 4 | val allDrivers: List, 5 | val allPassengers: List, 6 | val orders: List) 7 | 8 | data class Driver(val name: String) 9 | data class Passenger(val name: String) 10 | 11 | data class Order( 12 | val driver: Driver, 13 | val passengers: Collection, 14 | val duration: Int, 15 | val distance: Double, 16 | val discount: Double? = null 17 | ) { 18 | val cost: Double 19 | get() = (1 - (discount ?: 0.0)) * (duration + distance) 20 | } -------------------------------------------------------------------------------- /student/tasks/org/jetbrains/kotlinworkshop/student/single/_3TaxiPark/_1FakeDrivers.kt: -------------------------------------------------------------------------------- 1 | package org.jetbrains.kotlinworkshop.student.single._3TaxiPark 2 | 3 | // Find all the drivers that completed no orders 4 | fun TaxiPark.findFakeDrivers(): Set = 5 | TODO() -------------------------------------------------------------------------------- /student/tasks/org/jetbrains/kotlinworkshop/student/single/_3TaxiPark/_2FaithfulPassengers.kt: -------------------------------------------------------------------------------- 1 | package org.jetbrains.kotlinworkshop.student.single._3TaxiPark 2 | 3 | // Find all passengers having more than 'minTrips' number of trips 4 | fun TaxiPark.findFaithfulPassengers(minTrips: Int): List = 5 | TODO() -------------------------------------------------------------------------------- /student/tasks/org/jetbrains/kotlinworkshop/student/single/_3TaxiPark/_3FrequentPassengers.kt: -------------------------------------------------------------------------------- 1 | package org.jetbrains.kotlinworkshop.student.single._3TaxiPark 2 | 3 | // Find all passengers that were taken by this driver more than once 4 | fun TaxiPark.findFrequentPassengers(driver: Driver): List = 5 | TODO() -------------------------------------------------------------------------------- /student/tasks/org/jetbrains/kotlinworkshop/student/single/_3TaxiPark/_4SmartPassengers.kt: -------------------------------------------------------------------------------- 1 | package org.jetbrains.kotlinworkshop.student.single._3TaxiPark 2 | 3 | // Find passengers that used discounts for majority of the trips 4 | fun TaxiPark.findSmartPassengers(): Set = 5 | TODO() -------------------------------------------------------------------------------- /student/tasks/org/jetbrains/kotlinworkshop/student/single/_3TaxiPark/_5FrequentTripDuration.kt: -------------------------------------------------------------------------------- 1 | package org.jetbrains.kotlinworkshop.student.single._3TaxiPark 2 | 3 | // Find the most frequent trip interval duration (or several if there are many) 4 | // among 0-9 minutes, 10-19 minutes, 20-29 minutes etc. 5 | // If there's no duration info, return empty list. 6 | fun TaxiPark.findTheMostFrequentTripDurations(): List { 7 | TODO() 8 | } -------------------------------------------------------------------------------- /student/tasks/org/jetbrains/kotlinworkshop/student/single/_3TaxiPark/_6TestParetoPrinciple.kt: -------------------------------------------------------------------------------- 1 | package org.jetbrains.kotlinworkshop.student.single._3TaxiPark 2 | 3 | // Check whether 20% of the drivers make 80% of the profit 4 | fun TaxiPark.checkParetoPrinciple(): Boolean { 5 | TODO() 6 | } -------------------------------------------------------------------------------- /student/tasks/org/jetbrains/kotlinworkshop/student/single/_4Generics/GenericFunctions.kt: -------------------------------------------------------------------------------- 1 | package _7Generics 2 | 3 | /* 4 | Add a 'partitionTo' function that splits a collection into two collections according to the predicate. 5 | Uncomment the commented invocations of 'partitionTo' below and make them compile. 6 | 7 | There is a 'partition()' function in the standard library that always returns two newly created lists. 8 | You should write a function that splits the collection into two collections given as arguments. 9 | The signature of the 'toCollection()' function from the standard library might help you. 10 | */ 11 | 12 | fun List.partitionWordsAndLines(): Pair, List> { 13 | TODO() 14 | // return partitionTo(ArrayList(), ArrayList()) { s -> !s.contains(" ") } 15 | } 16 | 17 | fun Set.partitionLettersAndOtherSymbols(): Pair, Set> { 18 | TODO() 19 | // return partitionTo(HashSet(), HashSet()) { c -> c in 'a'..'z' || c in 'A'..'Z'} 20 | } -------------------------------------------------------------------------------- /student/tasks/org/jetbrains/kotlinworkshop/student/single/_5LazyProperty/LazyProperty.kt: -------------------------------------------------------------------------------- 1 | package org.jetbrains.kotlinworkshop.student.single._5LazyProperty 2 | 3 | // Add a custom getter to make the 'lazy' val really lazy. 4 | // It should be initialized by the invocation of 'initializer()' 5 | // at the moment of the first access. 6 | // You can add as many additional properties as you need. 7 | // Do not use delegated properties! 8 | 9 | class LazyProperty(val initializer: () -> Int) { 10 | val lazy: Int = TODO() 11 | } -------------------------------------------------------------------------------- /student/tasks/org/jetbrains/kotlinworkshop/student/single/_6WithApply/UsingWithApplyFunctions.kt: -------------------------------------------------------------------------------- 1 | package org.jetbrains.kotlinworkshop.student.single._6WithApply 2 | 3 | class BreakfastMenuItem { 4 | var name: String? = null 5 | var price: Double? = null 6 | var calories: Int? = null 7 | } 8 | 9 | fun initializeMenuItem(): BreakfastMenuItem { 10 | val menuItem = BreakfastMenuItem() 11 | menuItem.name = "Belgian Waffles" 12 | menuItem.price = 5.95 13 | menuItem.calories = 650 14 | return menuItem 15 | } 16 | 17 | fun initializeMenuItem1(): BreakfastMenuItem { 18 | TODO("Rewrite the 'initializeMenuItem' function using 'with'") 19 | } 20 | 21 | fun initializeMenuItem2(): BreakfastMenuItem { 22 | TODO("Rewrite the 'initializeMenuItem' function using 'apply'") 23 | } -------------------------------------------------------------------------------- /student/tasks/org/jetbrains/kotlinworkshop/student/single/_7CreatingDsl/BreakfastMenu.kt: -------------------------------------------------------------------------------- 1 | package org.jetbrains.kotlinworkshop.student.single._7CreatingDsl 2 | 3 | class BreakfastMenuItem { 4 | var name: String? = null 5 | var price: Double? = null 6 | var calories: Int? = null 7 | } 8 | 9 | class BreakfastMenu { 10 | val items = mutableListOf() 11 | } 12 | 13 | fun BreakfastMenu.item(init: BreakfastMenuItem.() -> Unit) { 14 | TODO("Create new menu item, initialize it and add it to the 'items' list") 15 | } 16 | 17 | fun breakfastMenu(init: BreakfastMenu.() -> Unit): BreakfastMenu { 18 | TODO("Create new BreakfastMenu and initialize it. All the items are added by 'init'.") 19 | // bonus: use the 'apply' function 20 | } -------------------------------------------------------------------------------- /student/tasks/org/jetbrains/kotlinworkshop/student/single/_7CreatingDsl/BreakfastMenuBonusTask.kt: -------------------------------------------------------------------------------- 1 | package org.jetbrains.kotlinworkshop.student.single._7CreatingDsl 2 | 3 | // Another bonus (Kotlin 1.1 feature). 4 | // Add the marker annotation to make impossible using "item" inside another "item". 5 | // The code below shouldn't compile. 6 | // See _3HtmlBuilders/html.kt for the example if necessary. 7 | 8 | fun createErroneousMenu() = breakfastMenu { 9 | item { 10 | name = "Belgian Waffles" 11 | price = 5.95 12 | calories = 650 13 | 14 | // using "item" shouldn't compile 15 | item { 16 | name = "Strawberry Belgian Waffles" 17 | price = 7.95 18 | calories = 900 19 | } 20 | } 21 | } -------------------------------------------------------------------------------- /student/tasks/org/jetbrains/kotlinworkshop/student/single/_7CreatingDsl/breakfastMenu.xml: -------------------------------------------------------------------------------- 1 | 2 | 3 | Belgian Waffles 4 | $5.95 5 | 650 6 | 7 | 8 | Strawberry Belgian Waffles 9 | $7.95 10 | 900 11 | 12 | 13 | Berry-Berry Belgian Waffles 14 | $8.95 15 | 900 16 | 17 | 18 | French Toast 19 | $4.50 20 | 600 21 | 22 | 23 | Homestyle Breakfast 24 | $6.95 25 | 950 26 | 27 | -------------------------------------------------------------------------------- /student/tasks/org/jetbrains/kotlinworkshop/student/single/_7CreatingDsl/createBreakfastMenu.kt: -------------------------------------------------------------------------------- 1 | package org.jetbrains.kotlinworkshop.student.single._7CreatingDsl 2 | 3 | fun createCustomMenu() = breakfastMenu { 4 | item { 5 | name = "Belgian Waffles" 6 | price = 5.95 7 | calories = 650 8 | } 9 | item { 10 | name = "Strawberry Belgian Waffles" 11 | price = 7.95 12 | calories = 900 13 | } 14 | item { 15 | name = "Berry-Berry Belgian Waffles" 16 | price = 8.95 17 | calories = 900 18 | } 19 | item { 20 | name = "French Toast" 21 | price = 4.50 22 | calories = 600 23 | } 24 | item { 25 | name = "Homestyle Breakfast" 26 | price = 6.95 27 | calories = 950 28 | } 29 | } -------------------------------------------------------------------------------- /student/tasks/org/jetbrains/kotlinworkshop/student/single/_8Conventions/MyDate.kt: -------------------------------------------------------------------------------- 1 | package org.jetbrains.kotlinworkshop.student.single._8Conventions 2 | 3 | data class MyDate(val year: Int, val month: Int, val dayOfMonth: Int) 4 | 5 | class DateRange(val start: MyDate, val endInclusive: MyDate) 6 | 7 | operator fun MyDate.rangeTo(other: MyDate): DateRange = TODO() 8 | 9 | enum class TimeInterval { 10 | DAY, 11 | WEEK, 12 | YEAR 13 | } -------------------------------------------------------------------------------- /student/tasks/org/jetbrains/kotlinworkshop/student/single/_8Conventions/MyDateUsage.kt: -------------------------------------------------------------------------------- 1 | package org.jetbrains.kotlinworkshop.student.single._8Conventions 2 | 3 | /* 4 | Task: Uncomment the commented code and make it compile by changing the MyDate class. 5 | */ 6 | 7 | fun task1(date1: MyDate, date2: MyDate): Boolean { 8 | TODO() 9 | // return date1 < date2 10 | } 11 | 12 | fun task2(date: MyDate, first: MyDate, last: MyDate): Boolean { 13 | TODO() 14 | // return date in DateRange(first, last) 15 | } 16 | 17 | fun task3(date: MyDate, first: MyDate, last: MyDate): Boolean { 18 | TODO() 19 | // return date in first..last 20 | } 21 | 22 | fun task4(today: MyDate): MyDate { 23 | TODO() 24 | // return today + YEAR + WEEK 25 | } 26 | 27 | fun task5(today: MyDate): MyDate { 28 | TODO() 29 | // return today + YEAR * 2 + WEEK * 3 + DAY * 5 30 | } 31 | -------------------------------------------------------------------------------- /student/tasks/org/jetbrains/kotlinworkshop/student/single/_8Conventions/MyDateUtil.kt: -------------------------------------------------------------------------------- 1 | package org.jetbrains.kotlinworkshop.student.single._8Conventions 2 | 3 | import org.jetbrains.kotlinworkshop.student.single._8Conventions.TimeInterval.* 4 | import java.util.* 5 | 6 | fun MyDate.nextDay() = addTimeIntervals(DAY, 1) 7 | 8 | fun MyDate.addTimeIntervals(timeInterval: TimeInterval, number: Int): MyDate { 9 | val c = Calendar.getInstance() 10 | c.set(year + if (timeInterval == YEAR) number else 0, month, dayOfMonth) 11 | var timeInMillis = c.timeInMillis 12 | val millisecondsInADay = 24 * 60 * 60 * 1000L 13 | timeInMillis += number * when (timeInterval) { 14 | DAY -> millisecondsInADay 15 | WEEK -> 7 * millisecondsInADay 16 | YEAR -> 0L 17 | } 18 | val result = Calendar.getInstance() 19 | result.timeInMillis = timeInMillis 20 | return MyDate(result.get(Calendar.YEAR), result.get(Calendar.MONTH), result.get(Calendar.DATE)) 21 | } -------------------------------------------------------------------------------- /student/tests/org/jetbrains/kotlinworkshop/student/single/_0Nullability/TestSendMessage.kt: -------------------------------------------------------------------------------- 1 | package org.jetbrains.kotlinworkshop.student.single._0Nullability 2 | 3 | import kotlin.test.* 4 | 5 | class TestSendMessage { 6 | fun testSendMessageToClient( 7 | client: Client?, 8 | message: String?, 9 | email: String? = null, 10 | shouldBeInvoked: Boolean = false 11 | ) { 12 | var invoked = false 13 | sendMessageToClient(client, message, object : Mailer { 14 | override fun sendMessage(actualEmail: String, actualMessage: String) { 15 | invoked = true 16 | assertEquals( 17 | message, actualMessage, "The message is not as expected:") 18 | assertEquals( 19 | email, actualEmail, "The email is not as expected:") 20 | } 21 | }) 22 | assertEquals(shouldBeInvoked, invoked, "The function 'sendMessage' should${if (shouldBeInvoked) "" else "n't"} be invoked") 23 | } 24 | 25 | @Test fun everythingIsOk() { 26 | testSendMessageToClient(Client(PersonalInfo("bob@gmail.com")), 27 | "Hi Bob! We have an awesome proposition for you...", 28 | "bob@gmail.com", 29 | true) 30 | } 31 | 32 | @Test fun noMessage() { 33 | testSendMessageToClient(Client(PersonalInfo("bob@gmail.com")), null) 34 | } 35 | 36 | @Test fun noEmail() { 37 | testSendMessageToClient(Client(PersonalInfo(null)), "Hi Bob! We have an awesome proposition for you...") 38 | } 39 | 40 | @Test fun noPersonalInfo() { 41 | testSendMessageToClient(Client(null), "Hi Bob! We have an awesome proposition for you...") 42 | } 43 | 44 | @Test fun noClient() { 45 | testSendMessageToClient(null, "Hi Bob! We have an awesome proposition for you...") 46 | } 47 | } -------------------------------------------------------------------------------- /student/tests/org/jetbrains/kotlinworkshop/student/single/_1BreakingSafety/_1TestNPE.kt: -------------------------------------------------------------------------------- 1 | package org.jetbrains.kotlinworkshop.student.single._1BreakingSafety 2 | 3 | 4 | import org.jetbrains.kotlinworkshop.student.single._1BreakingSafety.* 5 | import org.junit.jupiter.api.* 6 | import org.junit.jupiter.api.Test 7 | import kotlin.test.* 8 | 9 | class TestNPE { 10 | @Test 11 | fun testThrowingNPE() { 12 | assertFailsWith { 13 | mightThrowNPE() 14 | } 15 | } 16 | } -------------------------------------------------------------------------------- /student/tests/org/jetbrains/kotlinworkshop/student/single/_1BreakingSafety/_2TestNullInList.kt: -------------------------------------------------------------------------------- 1 | package org.jetbrains.kotlinworkshop.student.single._1BreakingSafety 2 | 3 | 4 | import org.jetbrains.kotlinworkshop.student.single._1BreakingSafety.* 5 | import org.junit.jupiter.api.* 6 | import org.junit.jupiter.api.Test 7 | import kotlin.test.* 8 | 9 | class NullInList { 10 | @Test 11 | fun testAddingNullToList() { 12 | val list: List = mightContainNull() 13 | assertFailsWith { 14 | for (i in list) { 15 | 16 | } 17 | } 18 | } 19 | } -------------------------------------------------------------------------------- /student/tests/org/jetbrains/kotlinworkshop/student/single/_1BreakingSafety/_3TestNotImmutableProperty.kt: -------------------------------------------------------------------------------- 1 | package org.jetbrains.kotlinworkshop.student.single._1BreakingSafety 2 | 3 | 4 | import org.jetbrains.kotlinworkshop.student.single._1BreakingSafety.* 5 | import org.junit.jupiter.api.* 6 | import org.junit.jupiter.api.Test 7 | import kotlin.test.* 8 | 9 | 10 | class TestNotImmutableProperty { 11 | @Test 12 | fun testDifferentValues() { 13 | val myClass = MyClass() 14 | assertNotEquals( 15 | myClass.myProperty, myClass.myProperty, "Property should return different values") 16 | } 17 | } -------------------------------------------------------------------------------- /student/tests/org/jetbrains/kotlinworkshop/student/single/_1BreakingSafety/_4TestNPEDuringInitialization.kt: -------------------------------------------------------------------------------- 1 | package org.jetbrains.kotlinworkshop.student.single._1BreakingSafety 2 | 3 | 4 | import org.jetbrains.kotlinworkshop.student.single._1BreakingSafety.* 5 | import org.junit.jupiter.api.* 6 | import org.junit.jupiter.api.Test 7 | import kotlin.test.* 8 | 9 | class NPEDuringInitialization { 10 | @Test 11 | fun testSubclassInitialization() { 12 | assertFailsWith { 13 | B("abc") 14 | } 15 | } 16 | } -------------------------------------------------------------------------------- /student/tests/org/jetbrains/kotlinworkshop/student/single/_2Shop/ShopBuilders.kt: -------------------------------------------------------------------------------- 1 | package org.jetbrains.kotlinworkshop.student.introduction._2Shop 2 | 3 | import org.jetbrains.kotlinworkshop.student.single._2Shop.* 4 | 5 | class ShopBuilder(val name: String) { 6 | val customers = arrayListOf() 7 | fun build(): Shop = Shop(name, customers) 8 | } 9 | 10 | fun shop(name: String, init: ShopBuilder.() -> Unit): Shop = ShopBuilder(name).apply(init).build() 11 | 12 | fun ShopBuilder.customer(name: String, city: City, init: CustomerBuilder.() -> Unit) { 13 | val customer = CustomerBuilder(name, city) 14 | customer.init() 15 | customers.add(customer.build()) 16 | } 17 | 18 | class CustomerBuilder(val name: String, val city: City) { 19 | val orders = arrayListOf() 20 | 21 | fun build(): Customer = Customer(name, city, orders) 22 | } 23 | 24 | fun CustomerBuilder.order(isDelivered: Boolean, vararg products: Product) { 25 | orders.add(Order(products.toList(), isDelivered)) 26 | } 27 | 28 | fun CustomerBuilder.order(vararg products: Product) = order(true, *products) 29 | 30 | -------------------------------------------------------------------------------- /student/tests/org/jetbrains/kotlinworkshop/student/single/_2Shop/TestShop.kt: -------------------------------------------------------------------------------- 1 | package org.jetbrains.kotlinworkshop.student.introduction._2Shop 2 | 3 | import org.jetbrains.kotlinworkshop.student.single._2Shop.* 4 | 5 | //products 6 | val idea = Product("IntelliJ IDEA Ultimate", 199.0) 7 | val reSharper = Product("ReSharper", 149.0) 8 | val dotTrace = Product("DotTrace", 159.0) 9 | val dotMemory = Product("DotTrace", 129.0) 10 | val dotCover = Product("DotCover", 99.0) 11 | val appCode = Product("AppCode", 99.0) 12 | val phpStorm = Product("PhpStorm", 99.0) 13 | val pyCharm = Product("PyCharm", 99.0) 14 | val rubyMine = Product("RubyMine", 99.0) 15 | val webStorm = Product("WebStorm", 49.0) 16 | val teamCity = Product("TeamCity", 299.0) 17 | val youTrack = Product("YouTrack", 500.0) 18 | 19 | //customers 20 | val lucas = "Lucas" 21 | val cooper = "Cooper" 22 | val nathan = "Nathan" 23 | val reka = "Reka" 24 | val bajram = "Bajram" 25 | val asuka = "Asuka" 26 | val riku = "Riku" 27 | 28 | //cities 29 | val Canberra = City("Canberra") 30 | val Vancouver = City("Vancouver") 31 | val Budapest = City("Budapest") 32 | val Ankara = City("Ankara") 33 | val Tokyo = City("Tokyo") 34 | 35 | val shop = shop("test shop") { 36 | customer(lucas, Canberra) { 37 | order(reSharper) 38 | order(reSharper, dotMemory, dotTrace) 39 | } 40 | customer(cooper, Canberra) {} 41 | customer(nathan, Vancouver) { 42 | order(rubyMine, webStorm) 43 | } 44 | customer(reka, Budapest) { 45 | order(isDelivered = false, products = *arrayOf(idea)) 46 | order(isDelivered = false, products = *arrayOf(idea)) 47 | order(idea) 48 | } 49 | customer(bajram, Ankara) { 50 | order(reSharper) 51 | } 52 | customer(asuka, Tokyo) { 53 | order(idea) 54 | } 55 | customer(riku, Tokyo) { 56 | order(phpStorm, phpStorm) 57 | order(phpStorm) 58 | } 59 | } 60 | 61 | val customers: Map = shop.customers.associateBy(Customer::name) 62 | 63 | val orderedProducts = setOf(idea, reSharper, dotTrace, dotMemory, rubyMine, webStorm, phpStorm) 64 | 65 | val sortedCustomers = listOf(cooper, nathan, bajram, asuka, lucas, riku, reka).map { customers[it] } 66 | 67 | val groupedByCities = mapOf( 68 | Canberra to listOf(lucas, cooper), 69 | Vancouver to listOf(nathan), 70 | Budapest to listOf(reka), 71 | Ankara to listOf(bajram), 72 | Tokyo to listOf(asuka, riku) 73 | ).mapValues { it.value.map { name -> customers[name] } } 74 | -------------------------------------------------------------------------------- /student/tests/org/jetbrains/kotlinworkshop/student/single/_2Shop/_10GroupBy.kt: -------------------------------------------------------------------------------- 1 | package org.jetbrains.kotlinworkshop.student.introduction._2Shop 2 | 3 | import org.jetbrains.kotlinworkshop.student.single._2Shop.* 4 | import org.junit.jupiter.api.* 5 | import org.junit.jupiter.api.Test 6 | import kotlin.test.* 7 | 8 | class _10GroupBy { 9 | @Test 10 | fun testGroupCustomersByCity() { 11 | assertEquals(groupedByCities, shop.groupCustomersByCity()) 12 | } 13 | } 14 | -------------------------------------------------------------------------------- /student/tests/org/jetbrains/kotlinworkshop/student/single/_2Shop/_11Partition.kt: -------------------------------------------------------------------------------- 1 | package org.jetbrains.kotlinworkshop.student.introduction._2Shop 2 | 3 | import org.jetbrains.kotlinworkshop.student.single._2Shop.* 4 | import org.junit.jupiter.api.* 5 | import org.junit.jupiter.api.Test 6 | import kotlin.test.* 7 | 8 | class _11Partition { 9 | @Test 10 | fun testGetCustomersWhoHaveMoreUndeliveredOrdersThanDelivered() { 11 | assertEquals(setOf(customers[reka]), shop.getCustomersWithMoreUndeliveredOrdersThanDelivered()) 12 | } 13 | } 14 | -------------------------------------------------------------------------------- /student/tests/org/jetbrains/kotlinworkshop/student/single/_2Shop/_12Fold.kt: -------------------------------------------------------------------------------- 1 | package org.jetbrains.kotlinworkshop.student.introduction._2Shop 2 | 3 | import org.jetbrains.kotlinworkshop.student.single._2Shop.* 4 | import org.junit.jupiter.api.* 5 | import org.junit.jupiter.api.Test 6 | import kotlin.test.* 7 | 8 | class _12Fold { 9 | @Test 10 | fun testGetProductsOrderedByAllCustomers() { 11 | val testShop = shop("test shop for 'fold'") { 12 | customer(lucas, Canberra) { 13 | order(idea) 14 | order(webStorm) 15 | } 16 | customer(reka, Budapest) { 17 | order(idea) 18 | order(youTrack) 19 | } 20 | } 21 | assertEquals(setOf(idea), testShop.getSetOfProductsOrderedByEveryCustomer()) 22 | } 23 | } 24 | -------------------------------------------------------------------------------- /student/tests/org/jetbrains/kotlinworkshop/student/single/_2Shop/_13CompoundTasks.kt: -------------------------------------------------------------------------------- 1 | package org.jetbrains.kotlinworkshop.student.introduction._2Shop 2 | 3 | import org.jetbrains.kotlinworkshop.student.single._2Shop.* 4 | import org.junit.jupiter.api.* 5 | import org.junit.jupiter.api.Test 6 | import kotlin.test.* 7 | 8 | class _13CompoundTasks { 9 | @Test 10 | fun testGetCustomersWhoOrderedProduct() { 11 | assertEquals(setOf(customers[reka], customers[asuka]), shop.getCustomersWhoOrderedProduct(idea)) 12 | } 13 | 14 | @Test fun testMostExpensiveDeliveredProduct() { 15 | val testShop = shop("test shop for 'most expensive delivered product'") { 16 | customer(lucas, Canberra) { 17 | order(isDelivered = false, products = *arrayOf(idea)) 18 | order(reSharper) 19 | } 20 | } 21 | assertEquals(reSharper, testShop.customers[0].getMostExpensiveDeliveredProduct()) 22 | } 23 | 24 | @Test fun testNumberOfTimesEachProductWasOrdered() { 25 | assertEquals(4, shop.getNumberOfTimesProductWasOrdered(idea)) 26 | } 27 | 28 | @Test fun testNumberOfTimesEachProductWasOrderedForRepeatedProduct() { 29 | assertEquals( 30 | 3, shop.getNumberOfTimesProductWasOrdered(reSharper), "A customer may order a product for several times") 31 | } 32 | 33 | @Test fun testNumberOfTimesEachProductWasOrderedForRepeatedInOrderProduct() { 34 | assertEquals( 35 | 3, shop.getNumberOfTimesProductWasOrdered(phpStorm), "An order may contain a particular product more than once") 36 | } 37 | } 38 | -------------------------------------------------------------------------------- /student/tests/org/jetbrains/kotlinworkshop/student/single/_2Shop/_14SmthWithCollections.kt: -------------------------------------------------------------------------------- 1 | package org.jetbrains.kotlinworkshop.student.introduction._2Shop 2 | 3 | import org.jetbrains.kotlinworkshop.student.single._2Shop.* 4 | import org.junit.jupiter.api.* 5 | import org.junit.jupiter.api.Test 6 | import kotlin.test.* 7 | 8 | class _14SmthWithCollections { 9 | @Test 10 | fun testCollectionOfOneElement() { 11 | doTest(listOf("a"), listOf("a")) 12 | } 13 | 14 | @Test fun testEmptyCollection() { 15 | doTest(null, listOf()) 16 | } 17 | 18 | @Test fun testSimpleCollection() { 19 | doTest(listOf("a", "c"), listOf("a", "bb", "c")) 20 | } 21 | 22 | @Test fun testCollectionWithEmptyStrings() { 23 | doTest(listOf("", "", "", ""), listOf("", "", "", "", "a", "bb", "ccc", "dddd")) 24 | } 25 | 26 | @Test fun testCollectionWithTwoGroupsOfMaximalSize() { 27 | doTest(listOf("a", "c"), listOf("a", "bb", "c", "dd")) 28 | } 29 | 30 | private fun doTest(expected: Collection?, argument: Collection) { 31 | assertEquals( 32 | expected, doSomethingStrangeWithCollection(argument), "The function 'doSomethingStrangeWithCollection' should do at least something with a collection:") 33 | } 34 | } -------------------------------------------------------------------------------- /student/tests/org/jetbrains/kotlinworkshop/student/single/_2Shop/_1Introduction.kt: -------------------------------------------------------------------------------- 1 | package org.jetbrains.kotlinworkshop.student.introduction._2Shop 2 | 3 | import org.jetbrains.kotlinworkshop.student.single._2Shop.* 4 | import org.junit.jupiter.api.* 5 | import org.junit.jupiter.api.Test 6 | import kotlin.test.* 7 | 8 | class _1Introduction { 9 | @Test 10 | fun testSetOfCustomers() { 11 | assertEquals(customers.values.toSet(), shop.getSetOfCustomers()) 12 | } 13 | } 14 | -------------------------------------------------------------------------------- /student/tests/org/jetbrains/kotlinworkshop/student/single/_2Shop/_2FilterMap.kt: -------------------------------------------------------------------------------- 1 | package org.jetbrains.kotlinworkshop.student.introduction._2Shop 2 | 3 | 4 | import org.jetbrains.kotlinworkshop.student.single._2Shop.* 5 | import org.junit.jupiter.api.* 6 | import org.junit.jupiter.api.Test 7 | import kotlin.test.* 8 | 9 | class _2FilterMap { 10 | @Test 11 | fun testCitiesCustomersAreFrom() { 12 | assertEquals(setOf(Canberra, Vancouver, Budapest, Ankara, Tokyo), shop.getCitiesCustomersAreFrom()) 13 | } 14 | 15 | /** 16 | * Returns the list of the customers who live in the city 'city' 17 | */ 18 | @Test fun testCustomersFromCity() { 19 | assertEquals(listOf(customers[lucas], customers[cooper]), shop.getCustomersFrom(Canberra)) 20 | } 21 | } 22 | -------------------------------------------------------------------------------- /student/tests/org/jetbrains/kotlinworkshop/student/single/_2Shop/_3AllAnyAndOtherPredicates.kt: -------------------------------------------------------------------------------- 1 | package org.jetbrains.kotlinworkshop.student.introduction._2Shop 2 | 3 | 4 | import org.jetbrains.kotlinworkshop.student.single._2Shop.* 5 | import org.junit.jupiter.api.* 6 | import org.junit.jupiter.api.Test 7 | import kotlin.test.* 8 | 9 | class _3AllAnyAndOtherPredicates { 10 | @Test 11 | fun testCustomerIsFromCity() { 12 | assertTrue(customers[lucas]!!.isFrom(Canberra)) 13 | assertFalse(customers[lucas]!!.isFrom(Budapest)) 14 | } 15 | 16 | @Test fun testAllCustomersAreFromCity() { 17 | assertFalse(shop.checkAllCustomersAreFrom(Canberra)) 18 | } 19 | 20 | @Test fun testAnyCustomerIsFromCity() { 21 | assertTrue(shop.hasCustomerFrom(Canberra)) 22 | } 23 | 24 | @Test fun testCountCustomersFromCity() { 25 | assertEquals(2, shop.countCustomersFrom(Canberra)) 26 | } 27 | 28 | @Test fun testAnyCustomerFromCity() { 29 | assertEquals(customers[lucas], shop.findAnyCustomerFrom(Canberra)) 30 | assertEquals(null, shop.findAnyCustomerFrom(City("Chicago"))) 31 | } 32 | } 33 | -------------------------------------------------------------------------------- /student/tests/org/jetbrains/kotlinworkshop/student/single/_2Shop/_4FlatMap.kt: -------------------------------------------------------------------------------- 1 | package org.jetbrains.kotlinworkshop.student.introduction._2Shop 2 | 3 | 4 | import org.jetbrains.kotlinworkshop.student.single._2Shop.* 5 | import org.junit.jupiter.api.* 6 | import org.junit.jupiter.api.Test 7 | import kotlin.test.* 8 | 9 | class _4FlatMap { 10 | @Test 11 | fun testGetOrderedProductsSet() { 12 | assertEquals(setOf(idea), customers[reka]!!.orderedProducts) 13 | } 14 | 15 | @Test fun testGetAllOrderedProducts() { 16 | assertEquals(orderedProducts, shop.allOrderedProducts) 17 | } 18 | } 19 | -------------------------------------------------------------------------------- /student/tests/org/jetbrains/kotlinworkshop/student/single/_2Shop/_5MaxMin.kt: -------------------------------------------------------------------------------- 1 | package org.jetbrains.kotlinworkshop.student.introduction._2Shop 2 | 3 | import org.jetbrains.kotlinworkshop.student.single._2Shop.* 4 | import org.junit.jupiter.api.* 5 | import org.junit.jupiter.api.Test 6 | import kotlin.test.* 7 | 8 | class _5MaxMin { 9 | @Test 10 | fun testCustomerWithMaximumNumberOfOrders() { 11 | assertEquals(customers[reka], shop.getCustomerWithMaximumNumberOfOrders()) 12 | } 13 | 14 | @Test fun testTheMostExpensiveOrderedProduct() { 15 | assertEquals(rubyMine, customers[nathan]!!.getMostExpensiveOrderedProduct()) 16 | } 17 | } 18 | -------------------------------------------------------------------------------- /student/tests/org/jetbrains/kotlinworkshop/student/single/_2Shop/_6Sort.kt: -------------------------------------------------------------------------------- 1 | package org.jetbrains.kotlinworkshop.student.introduction._2Shop 2 | 3 | import org.jetbrains.kotlinworkshop.student.single._2Shop.* 4 | import org.junit.jupiter.api.* 5 | import org.junit.jupiter.api.Test 6 | import kotlin.test.* 7 | 8 | class _6Sort { 9 | @Test 10 | fun testGetCustomersSortedByNumberOfOrders() { 11 | assertEquals(sortedCustomers, shop.getCustomersSortedByNumberOfOrders()) 12 | } 13 | } 14 | -------------------------------------------------------------------------------- /student/tests/org/jetbrains/kotlinworkshop/student/single/_2Shop/_7Sum.kt: -------------------------------------------------------------------------------- 1 | package org.jetbrains.kotlinworkshop.student.introduction._2Shop 2 | 3 | import org.jetbrains.kotlinworkshop.student.single._2Shop.* 4 | import org.junit.jupiter.api.* 5 | import org.junit.jupiter.api.Test 6 | import kotlin.test.* 7 | 8 | class _7Sum { 9 | @Test fun testGetTotalOrderPrice() { 10 | assertEquals(148.0, customers[nathan]!!.getTotalOrderPrice()) 11 | } 12 | 13 | @Test 14 | fun testTotalPriceForRepeatedProducts() { 15 | assertEquals(586.0, customers[lucas]!!.getTotalOrderPrice()) 16 | } 17 | } 18 | -------------------------------------------------------------------------------- /student/tests/org/jetbrains/kotlinworkshop/student/single/_2Shop/_8Zip.kt: -------------------------------------------------------------------------------- 1 | package org.jetbrains.kotlinworkshop.student.introduction._2Shop 2 | 3 | import org.jetbrains.kotlinworkshop.student.single._2Shop.* 4 | import org.junit.jupiter.api.* 5 | import org.junit.jupiter.api.Test 6 | import kotlin.test.* 7 | 8 | class _8Zip { 9 | @Test 10 | fun testZipNameAndCustomer() { 11 | assertEquals(customers.toList(), shop.zipNameAndCustomer()) 12 | } 13 | } -------------------------------------------------------------------------------- /student/tests/org/jetbrains/kotlinworkshop/student/single/_2Shop/_9AssociateBy.kt: -------------------------------------------------------------------------------- 1 | package org.jetbrains.kotlinworkshop.student.introduction._2Shop 2 | 3 | import org.jetbrains.kotlinworkshop.student.single._2Shop.* 4 | import org.junit.jupiter.api.* 5 | import org.junit.jupiter.api.Test 6 | import kotlin.test.* 7 | 8 | class _9AssociateBy { 9 | @Test 10 | fun testAssociateCustomersByName() { 11 | assertEquals(customers, shop.associateCustomersByName()) 12 | } 13 | } -------------------------------------------------------------------------------- /student/tests/org/jetbrains/kotlinworkshop/student/single/_3HtmlBuilders/TestHtmlBuilders.kt: -------------------------------------------------------------------------------- 1 | package org.jetbrains.kotlinworkshop.student.single._3HtmlBuilders 2 | 3 | import org.junit.jupiter.api.* 4 | import org.junit.jupiter.api.Test 5 | import kotlin.test.* 6 | 7 | class TestHtmlBuilders { 8 | @Test 9 | fun productTableIsFilled() { 10 | val result = renderProductTable() 11 | println(renderProductTable()) 12 | assertTrue(result.contains("cactus"), "Product table should contain corresponding data") 13 | } 14 | 15 | @Test fun productTableIsColored() { 16 | val result = renderProductTable() 17 | assertTrue(result.contains("bgcolor"), "Product table should be colored") 18 | } 19 | 20 | @Test fun allColorsAreUsed() { 21 | val result = renderProductTable() 22 | val colors = listOf("#b9c9fe", "#dce4ff", "#eff2ff") 23 | assertTrue(colors.all { result.contains(it) }, "Product table should be colored in chess order") 24 | } 25 | } 26 | -------------------------------------------------------------------------------- /student/tests/org/jetbrains/kotlinworkshop/student/single/_3TaxiPark/TestTaxiParkUtil.kt: -------------------------------------------------------------------------------- 1 | package org.jetbrains.kotlinworkshop.student.introduction._3TaxiPark 2 | 3 | import org.jetbrains.kotlinworkshop.student.single._3TaxiPark.* 4 | 5 | internal val drivers = (1..10).map { Driver("Driver$it") } 6 | internal val passengers = (1..10).map { Passenger("Passenger$it") } 7 | 8 | internal fun driver(i: Int) = drivers.getOrNull(i - 1) ?: throw IllegalArgumentException("Invalid driver index: $i") 9 | internal fun passenger(i: Int) = passengers.getOrNull(i - 1) ?: throw IllegalArgumentException("Invalid passenger index: $i") 10 | 11 | internal fun drivers(range: IntRange) = range.map(::driver) 12 | internal fun drivers(vararg indices: Int) = indices.map(::driver) 13 | internal fun passengers(range: IntRange) = range.map(::passenger) 14 | internal fun passengers(vararg indices: Int) = indices.map(::passenger) 15 | 16 | internal fun taxiPark(driverIndexes: IntRange, passengerIndexes: IntRange, orders: List) = 17 | TaxiPark(drivers(driverIndexes), passengers(passengerIndexes), orders.toList()) 18 | 19 | internal fun taxiPark(driverIndexes: IntRange, passengerIndexes: IntRange, vararg orders: Order) = 20 | taxiPark(driverIndexes, passengerIndexes, orders.toList()) 21 | 22 | internal fun order(driverIndex: Int, vararg passengerIndexes: Int, duration: Int = 10, distance: Double = 10.0, discount: Double? = null) = 23 | Order(driver(driverIndex), passengers(*passengerIndexes), duration, distance, discount) -------------------------------------------------------------------------------- /student/tests/org/jetbrains/kotlinworkshop/student/single/_3TaxiPark/_1TestFakeDrivers.kt: -------------------------------------------------------------------------------- 1 | package org.jetbrains.kotlinworkshop.student.introduction._3TaxiPark 2 | 3 | import org.jetbrains.kotlinworkshop.student.single._3TaxiPark.* 4 | import org.junit.jupiter.api.* 5 | import org.junit.jupiter.api.Test 6 | import kotlin.test.* 7 | 8 | class _1TestFakeDrivers { 9 | @Test 10 | fun testFakeDrivers() { 11 | val park = taxiPark(driverIndexes = 1..3, passengerIndexes = 1..2, 12 | orders = listOf(order(driverIndex = 1, passengerIndexes = *intArrayOf(1)), order(1, 2))) 13 | assertEquals(drivers(2, 3).toSet(), park.findFakeDrivers()) 14 | } 15 | 16 | @Test 17 | fun testNoFakeDrivers() { 18 | val park = taxiPark(1..2, 1..2, order(1, 1), order(2, 2)) 19 | assertTrue(park.findFakeDrivers().isEmpty()) 20 | } 21 | 22 | } -------------------------------------------------------------------------------- /student/tests/org/jetbrains/kotlinworkshop/student/single/_3TaxiPark/_2TestFaithfulPassengers.kt: -------------------------------------------------------------------------------- 1 | package org.jetbrains.kotlinworkshop.student.introduction._3TaxiPark 2 | 3 | 4 | import org.jetbrains.kotlinworkshop.student.single._3TaxiPark.* 5 | import org.junit.jupiter.api.* 6 | import org.junit.jupiter.api.Test 7 | import kotlin.test.* 8 | 9 | class _2TestFaithfulPassengers { 10 | @Test 11 | fun testFaithfulPassengersMoreThanMin() { 12 | val park = taxiPark(1..1, 1..2, 13 | order(1, 1), order(1, 2), order(1, 2)) 14 | assertEquals(passengers(2), park.findFaithfulPassengers(1)) 15 | } 16 | 17 | @Test 18 | fun testNoFaithfulPassengers() { 19 | val park = taxiPark(1..1, 1..2, 20 | order(1, 1), order(1, 2)) 21 | assertTrue(park.findFaithfulPassengers(1).isEmpty()) 22 | } 23 | 24 | @Test 25 | fun testFaithfulPassenger() { 26 | val park = taxiPark(1..2, 1..3, 27 | order(1, 2), order(1, 2), order(2, 2), order(2, 2)) 28 | assertEquals(passengers(2), park.findFaithfulPassengers(3)) 29 | } 30 | 31 | @Test 32 | fun testFaithfulPassengers() { 33 | val park = taxiPark(1..3, 1..5, 34 | order(1, 1), order(2, 1), order(1, 4), order(3, 4), order(1, 5), order(2, 5), order(2, 2)) 35 | assertEquals(passengers(1, 4, 5), park.findFaithfulPassengers(1)) 36 | } 37 | } 38 | -------------------------------------------------------------------------------- /student/tests/org/jetbrains/kotlinworkshop/student/single/_3TaxiPark/_3TestFrequentPassengers.kt: -------------------------------------------------------------------------------- 1 | package org.jetbrains.kotlinworkshop.student.introduction._3TaxiPark 2 | 3 | 4 | import org.jetbrains.kotlinworkshop.student.single._3TaxiPark.* 5 | import org.junit.jupiter.api.* 6 | import org.junit.jupiter.api.Test 7 | import kotlin.test.* 8 | 9 | class _3TestFrequentPassengers { 10 | @Test 11 | fun testOnlyPair() { 12 | val park = taxiPark(1..1, 1..1, order(1, 1), order(1, 1)) 13 | assertEquals(passengers(1), park.findFrequentPassengers(driver(1))) 14 | } 15 | 16 | @Test 17 | fun testFrequentPassengers() { 18 | val park = taxiPark(1..2, 1..4, order(1, 1), order(1, 1), order(1, 1, 3), order(1, 3), order(1, 2), order(2, 2)) 19 | assertEquals(passengers(1, 3), park.findFrequentPassengers(driver(1))) 20 | } 21 | 22 | @Test 23 | fun testNoFrequentPassengers() { 24 | val park = taxiPark(1..2, 1..4, order(1, 1), order(1, 1), order(1, 1, 3), order(1, 3), order(1, 2), order(2, 2)) 25 | assertTrue(park.findFrequentPassengers(driver(2)).isEmpty()) 26 | } 27 | } -------------------------------------------------------------------------------- /student/tests/org/jetbrains/kotlinworkshop/student/single/_3TaxiPark/_4TestSmartPassengers.kt: -------------------------------------------------------------------------------- 1 | package org.jetbrains.kotlinworkshop.student.introduction._3TaxiPark 2 | 3 | 4 | import org.jetbrains.kotlinworkshop.student.single._3TaxiPark.* 5 | import org.junit.jupiter.api.* 6 | import org.junit.jupiter.api.Test 7 | import kotlin.test.* 8 | 9 | class _4TestSmartPassengers { 10 | @Test 11 | fun testSmartPassengers() { 12 | val park = taxiPark(1..2, 1..2, order(1, 1, discount = 0.1), order(2, 2)) 13 | assertEquals(passengers(1).toSet(), park.findSmartPassengers()) 14 | } 15 | 16 | @Test 17 | fun testMoreThenMajorityDiscountTrips() { 18 | val park = taxiPark(1..1, 1..1, order(1, 1, discount = 0.1), order(1, 1, discount = 0.2), order(1, 1)) 19 | assertEquals(passengers(1).toSet(), park.findSmartPassengers()) 20 | } 21 | 22 | @Test 23 | fun testLessThenMajorityDiscountTrips() { 24 | val park = taxiPark(1..1, 1..1, order(1, 1), order(1, 1), order(1, 1, discount = 0.2), order(1, 1)) 25 | assertTrue(park.findSmartPassengers().isEmpty()) 26 | } 27 | } -------------------------------------------------------------------------------- /student/tests/org/jetbrains/kotlinworkshop/student/single/_3TaxiPark/_5FrequentTripDuration.kt: -------------------------------------------------------------------------------- 1 | package org.jetbrains.kotlinworkshop.student.introduction._3TaxiPark 2 | 3 | 4 | import org.jetbrains.kotlinworkshop.student.single._3TaxiPark.* 5 | import org.junit.jupiter.api.* 6 | import org.junit.jupiter.api.Test 7 | import kotlin.test.* 8 | 9 | class _5FrequentTripDuration { 10 | 11 | @Test 12 | fun testNoDurationInfo() { 13 | assertTrue(taxiPark(1..1, 1..1).findTheMostFrequentTripDurations().isEmpty()) 14 | } 15 | 16 | @Test 17 | fun testSeveralFrequent() { 18 | val park = taxiPark(1..1, 1..1, order(1, 1, duration = 11), order(1, 1, duration = 12), 19 | order(1, 1, duration = 25), order(1, 1, duration = 26)) 20 | assertEquals(listOf(10..19, 20..29), park.findTheMostFrequentTripDurations()) 21 | } 22 | 23 | @Test 24 | fun testTheMostFrequentTripDuration() { 25 | val park = taxiPark(1..3, 1..5, order(1, 1, duration = 10), order(3, 4, duration = 30), 26 | order(1, 2, duration = 20), order(2, 3, duration = 30)) 27 | assertEquals(listOf(30..39), park.findTheMostFrequentTripDurations()) 28 | } 29 | } -------------------------------------------------------------------------------- /student/tests/org/jetbrains/kotlinworkshop/student/single/_3TaxiPark/_6TestParetoPrinciple.kt: -------------------------------------------------------------------------------- 1 | package org.jetbrains.kotlinworkshop.student.introduction._3TaxiPark 2 | 3 | 4 | import org.jetbrains.kotlinworkshop.student.single._3TaxiPark.* 5 | import org.junit.jupiter.api.* 6 | import org.junit.jupiter.api.Test 7 | import kotlin.test.* 8 | 9 | class _6TestParetoPrinciple { 10 | @Test 11 | fun testParetoPrincipleSucceeds() { 12 | // 20% of the drivers: 1 13 | // the profit of the first driver: 500 14 | // the profit of all: 620 15 | // 500 >= 0.8 * 620 = 496 16 | val park = taxiPark(1..8, 1..8, order(1, 1, duration = 250, distance = 250.0), 17 | order(2, 2), order(3, 3), order(4, 4), order(5, 5), order(6, 6), order(7, 7)) 18 | assertTrue(park.checkParetoPrinciple()) 19 | } 20 | 21 | @Test 22 | fun testRandomDriverIsTheBest() { 23 | // the same as before, the best driver is now #5 24 | val park = taxiPark(1..8, 1..8, order(5, 1, duration = 250, distance = 250.0), 25 | order(2, 2), order(3, 3), order(4, 4), order(6, 6), order(7, 7), order(8, 8)) 26 | assertTrue(park.checkParetoPrinciple()) 27 | } 28 | 29 | @Test 30 | fun testSeveralBestDrivers() { 31 | // 20% of the drivers: 1, 10 32 | // the profit of 1, 10: 800 33 | // the profit of all: 940 34 | // 800 >= 0.8 * 940 = 752 35 | val park = taxiPark(1..10, 1..10, 36 | order(1, 1, duration = 200, distance = 200.0), 37 | order(10, 10, duration = 200, distance = 200.0), 38 | order(2, 2), order(3, 3), order(4, 4), order(5, 5), order(6, 6), order(7, 7), order(8, 8)) 39 | assertTrue(park.checkParetoPrinciple()) 40 | } 41 | 42 | @Test 43 | fun testNotEnoughDrivers() { 44 | // the first driver doesn't make up 20% 45 | val park = taxiPark(1..4, 1..4, order(1, 1, duration = 110, distance = 110.0), 46 | order(2, 2), order(3, 3), order(4, 4)) 47 | assertFalse(park.checkParetoPrinciple()) 48 | } 49 | 50 | @Test 51 | fun testParetoPrincipleFails() { 52 | // 20% of the drivers: 1 53 | // the profit of the first driver: 220 54 | // the profit of all: 300 55 | // 220 < 0.8 * 300 = 240 56 | val park = taxiPark(1..5, 1..5, order(1, 1, duration = 110, distance = 110.0), 57 | order(2, 2), order(3, 3), order(4, 4), order(5, 5)) 58 | assertFalse(park.checkParetoPrinciple()) 59 | } 60 | 61 | @Test 62 | fun testExactly80Percent() { 63 | // 20% of the drivers: 1 64 | // the profit of the first driver: 240 65 | // the profit of all: 300 66 | // 240 >= 0.8 * 300 = 240 67 | 68 | // tip: Use BigDecimal instead of double for comparison 69 | val park = taxiPark(1..5, 1..5, order(1, 1, duration = 120, distance = 120.0), 70 | order(2, 2), order(3, 3), order(4, 4)) 71 | assertFalse(park.checkParetoPrinciple()) 72 | } 73 | } -------------------------------------------------------------------------------- /student/tests/org/jetbrains/kotlinworkshop/student/single/_4Generics/TestGenericFunction.kt: -------------------------------------------------------------------------------- 1 | package org.jetbrains.kotlinworkshop.student.single._4Generics 2 | 3 | 4 | import _7Generics.* 5 | import org.junit.jupiter.api.* 6 | import org.junit.jupiter.api.Test 7 | import kotlin.test.* 8 | 9 | class TestGenericFunction { 10 | @Test 11 | fun testPartitionWordsAndLines() { 12 | val (words, lines) = listOf("a", "a b", "c", "d e").partitionWordsAndLines() 13 | assertEquals(listOf("a", "c"), words) 14 | assertEquals(listOf("a b", "d e"), lines) 15 | } 16 | 17 | @Test fun testPartitionLettersAndOtherSymbols() { 18 | val (letters, other) = setOf('a', '%', 'r', '}').partitionLettersAndOtherSymbols() 19 | assertEquals(setOf('a', 'r'), letters) 20 | assertEquals(setOf('%', '}'), other) 21 | } 22 | } -------------------------------------------------------------------------------- /student/tests/org/jetbrains/kotlinworkshop/student/single/_5LazyProperty/TestLazyProperty.kt: -------------------------------------------------------------------------------- 1 | package org.jetbrains.kotlinworkshop.student.single._5LazyProperty 2 | 3 | import org.junit.jupiter.api.* 4 | import org.junit.jupiter.api.Test 5 | import kotlin.test.* 6 | 7 | class TestLazyProperty { 8 | @Test 9 | fun testLazy() { 10 | var initialized = false 11 | val lazyProperty = LazyProperty({ initialized = true; 42 }) 12 | assertFalse(initialized, "Property shouldn't be initialized before access") 13 | val result: Int = lazyProperty.lazy 14 | assertTrue(initialized, "Property should be initialized after access") 15 | assertEquals(42, result) 16 | } 17 | 18 | @Test fun initializedOnce() { 19 | var initialized = 0 20 | val lazyProperty = LazyProperty({ initialized++; 42 }) 21 | lazyProperty.lazy 22 | lazyProperty.lazy 23 | assertEquals(1, initialized, "Lazy property should be initialized once") 24 | 25 | } 26 | } 27 | -------------------------------------------------------------------------------- /student/tests/org/jetbrains/kotlinworkshop/student/single/_6WithApply/TestUsingWithApplyFunctions.kt: -------------------------------------------------------------------------------- 1 | package org.jetbrains.kotlinworkshop.student.single._6WithApply 2 | 3 | import org.junit.jupiter.api.* 4 | import org.junit.jupiter.api.Test 5 | import kotlin.test.* 6 | 7 | 8 | class TestUsingWithApplyFunctions { 9 | @Test 10 | fun testUsingWith() { 11 | val menuItem = initializeMenuItem1() 12 | val message = "Menu item should initialized (using 'with' function)" 13 | assertEquals("Belgian Waffles", menuItem.name, message) 14 | assertEquals(5.95, menuItem.price, message) 15 | assertEquals(650, menuItem.calories, message) 16 | } 17 | 18 | @Test 19 | fun testUsingApply() { 20 | val menuItem = initializeMenuItem2() 21 | val message = "Menu item should initialized (using 'apply' function)" 22 | assertEquals("Belgian Waffles", menuItem.name, message) 23 | assertEquals(5.95, menuItem.price, message) 24 | assertEquals(650, menuItem.calories, message) 25 | } 26 | } -------------------------------------------------------------------------------- /student/tests/org/jetbrains/kotlinworkshop/student/single/_7CreatingDsl/TestBreakfastMenuCreation.kt: -------------------------------------------------------------------------------- 1 | package org.jetbrains.kotlinworkshop.student.single._7CreatingDsl 2 | 3 | 4 | import org.junit.jupiter.api.* 5 | import org.junit.jupiter.api.Test 6 | import kotlin.test.* 7 | 8 | class TestBreakfastMenuCreation { 9 | @Test 10 | fun testMenuIsCreated() { 11 | val menu = createCustomMenu() 12 | val message = "Menu items should be added to the menu" 13 | assertEquals(5, menu.items.size, message) 14 | assertEquals("French Toast", menu.items[3].name, message) 15 | assertEquals(900, menu.items[2].calories, message) 16 | assertEquals(6.95, menu.items[4].price, message) 17 | } 18 | } -------------------------------------------------------------------------------- /student/tests/org/jetbrains/kotlinworkshop/student/single/_8Conventions/DateUtil.kt: -------------------------------------------------------------------------------- 1 | package org.jetbrains.kotlinworkshop.student.single._8Conventions 2 | 3 | 4 | val MyDate.s: String get() = "($year-$month-$dayOfMonth)" -------------------------------------------------------------------------------- /student/tests/org/jetbrains/kotlinworkshop/student/single/_8Conventions/TestTask1.kt: -------------------------------------------------------------------------------- 1 | package org.jetbrains.kotlinworkshop.student.single._8Conventions 2 | 3 | import org.junit.jupiter.api.* 4 | import org.junit.jupiter.api.Test 5 | import kotlin.test.* 6 | 7 | class TestTask1 { 8 | @Test 9 | fun testDateComparison() { 10 | assertTrue(task1(MyDate(2014, 1, 1), MyDate(2014, 1, 2))) 11 | } 12 | 13 | @Test fun testBefore() { 14 | val first = MyDate(2014, 5, 10) 15 | val second = MyDate(2014, 7, 11) 16 | assertTrue(first < second, "The date ${first.s} should be before ${second.s}") 17 | } 18 | 19 | @Test fun testAfter() { 20 | val first = MyDate(2014, 10, 20) 21 | val second = MyDate(2014, 7, 11) 22 | assertTrue(first > second, "The date ${first.s} should be after ${second.s}") 23 | } 24 | 25 | operator fun MyDate.compareTo(other: MyDate): Int = TODO("This function shouldn't be called if MyDate implements 'Comparable'") 26 | } -------------------------------------------------------------------------------- /student/tests/org/jetbrains/kotlinworkshop/student/single/_8Conventions/TestTask2.kt: -------------------------------------------------------------------------------- 1 | package org.jetbrains.kotlinworkshop.student.single._8Conventions 2 | 3 | import org.junit.jupiter.api.* 4 | import org.junit.jupiter.api.Test 5 | import kotlin.test.* 6 | 7 | class TestTask2 { 8 | fun doTest(date: MyDate, first: MyDate, last: MyDate, shouldBeInRange: Boolean) { 9 | val message = "The date ${date.s} should${if (shouldBeInRange) "" else "n't"} be in range: ${first.s}..${last.s}" 10 | assertEquals(shouldBeInRange, task2(date, first, last), message) 11 | } 12 | 13 | @Test 14 | fun testInRange() { 15 | doTest(MyDate(2014, 3, 22), MyDate(2014, 1, 1), MyDate(2015, 1, 1), shouldBeInRange = true) 16 | } 17 | 18 | @Test fun testBefore() { 19 | doTest(MyDate(2013, 3, 22), MyDate(2014, 1, 1), MyDate(2015, 1, 1), shouldBeInRange = false) 20 | } 21 | 22 | @Test fun testAfter() { 23 | doTest(MyDate(2015, 3, 22), MyDate(2014, 1, 1), MyDate(2015, 1, 1), shouldBeInRange = false) 24 | } 25 | } -------------------------------------------------------------------------------- /student/tests/org/jetbrains/kotlinworkshop/student/single/_8Conventions/TestTask3.kt: -------------------------------------------------------------------------------- 1 | package org.jetbrains.kotlinworkshop.student.single._8Conventions 2 | 3 | import org.junit.jupiter.api.* 4 | import org.junit.jupiter.api.Test 5 | import kotlin.test.* 6 | 7 | class TestTask3 { 8 | fun doTest(date: MyDate, first: MyDate, last: MyDate, shouldBeInRange: Boolean) { 9 | val message = "The date ${date.s} should${if (shouldBeInRange) "" else "n't"} be in range: ${first.s}..${last.s}" 10 | assertEquals(shouldBeInRange, task3(date, first, last), message) 11 | } 12 | 13 | @Test 14 | fun testInRange() { 15 | doTest(MyDate(2014, 3, 22), MyDate(2014, 1, 1), MyDate(2015, 1, 1), shouldBeInRange = true) 16 | } 17 | 18 | @Test fun testBefore() { 19 | doTest(MyDate(2013, 3, 22), MyDate(2014, 1, 1), MyDate(2015, 1, 1), shouldBeInRange = false) 20 | } 21 | 22 | @Test fun testAfter() { 23 | doTest(MyDate(2015, 3, 22), MyDate(2014, 1, 1), MyDate(2015, 1, 1), shouldBeInRange = false) 24 | } 25 | } -------------------------------------------------------------------------------- /student/tests/org/jetbrains/kotlinworkshop/student/single/_8Conventions/TestTask4And5.kt: -------------------------------------------------------------------------------- 1 | package org.jetbrains.kotlinworkshop.student.single._8Conventions 2 | 3 | import org.junit.jupiter.api.* 4 | import org.junit.jupiter.api.Test 5 | import kotlin.test.* 6 | 7 | class TestTask4And5 { 8 | @Test 9 | fun testAddTimeIntervals() { 10 | assertEquals(MyDate(2014, 5, 22), MyDate(1983, 5, 22).addTimeIntervals(TimeInterval.YEAR, 31)) 11 | assertEquals(MyDate(1983, 5, 29), MyDate(1983, 5, 22).addTimeIntervals(TimeInterval.DAY, 7)) 12 | assertEquals(MyDate(1983, 5, 29), MyDate(1983, 5, 22).addTimeIntervals(TimeInterval.WEEK, 1)) 13 | } 14 | 15 | @Test fun testAddOneTimeInterval() { 16 | assertEquals(MyDate(2015, 5, 8), task4(MyDate(2014, 5, 1))) 17 | } 18 | 19 | @Test fun testOneMonth() { 20 | assertEquals(MyDate(2016, 0, 27), task5(MyDate(2014, 0, 1))) 21 | } 22 | 23 | @Test fun testMonthChange() { 24 | assertEquals(MyDate(2016, 1, 20), task5(MyDate(2014, 0, 25))) 25 | } 26 | } 27 | --------------------------------------------------------------------------------