sylhare/Kotlin

View on GitHub
README.md

Summary

Maintainability
Test Coverage
# Kotlin
[![Build Status](https://travis-ci.org/sylhare/Kotlin.svg?branch=master)](https://travis-ci.org/sylhare/Kotlin) [![Maintainability](https://api.codeclimate.com/v1/badges/94ef0be8c89785a0db0b/maintainability)](https://codeclimate.com/github/sylhare/Kotlin/maintainability) 
[![codecov](https://codecov.io/gh/sylhare/Kotlin/branch/master/graph/badge.svg)](https://codecov.io/gh/sylhare/Kotlin)

## Introduction
Kotlin is made by JetBrains (the same as that did IntelliJ the IDE).

See their website here:
  - [Kotlin](https://kotlinlang.org/)
  - [Getting started](https://kotlinlang.org/docs/tutorials/getting-started.html)
  - [Kotlin 101](https://sylhare.github.io/2019/12/02/Kotlin-101.html)

## Get started

Compiled with Java11.

To use with IntelliJ, you can select your project SDK, if you have multiple ones.
Use `File | Project Structure... | Project Settings | Projects` to choose `Java 11`.

### With kotlinc

If you are not using intellij, you can run with:

```bash
kotlinc hello.kt
```

### With gradle

You need to create the gradle file `build.gradle` (support [groovy or kotlin](https://kotlinlang.org/docs/reference/using-gradle.html)) then add dependencies and configurations.

For gradle to pick up the source and test files, you will need to organise your folders like:

```bash
└── src
    ├── main
    │   └── kotlin
    │       └── package
    └── test
        └── kotlin
            └── package

```

You can now try to run the tests (using the gradle wrapper `./gradlew` instead of `gradle` to
use the gradle version with which the project has been built with):

```bash
./gradlew test
```

And the complete one with coverage:

```bash
./gradlew clean build test jacocoTestReport
```

## Object-oriented

Some principles

- _Inheritance_ : kill off duplicate codes 
    - Implement with a Mother class implemented by a daughter class
- _Polymorphism_ : abstraction of implementation
    - Implement using interface and generic functions 
- _Encapsulation_ : hiding the changes, protects data
    - Implement by using restrictive access to data or contructers

Objects comparison:

- `equals`: should not throw an exception 
- `hashCode`: to compare (find) the object in a list

Encapsulation problems:

- Don't use `setSomething` and `getSomething` if you need _getters / setters_ but rather:
    - A Method with a verb to change something
    - A property with a noun to have the value of something     
- Control the data flow
     - You want to control how the value of your object is handled
    - You don't want anyone using the data without knowing how to
    - Make everything as private as possible
- Data object, feature envy
- Classes finishing by `-er` or `-or`
    - Should be a job of the class, or implemented as a pattern

## Tips

- Use ``` ` ``` (back tick) to define method's name with space:

```kotlin
@Test
fun `valid parameters` { ... }
```

- Overload Objects to generate new ones easily:

```kotlin
val Number.teaspoons get() = Quantity(this, Unit.teaspoon)

Quantity(1.5, Unit.teasponn) 
// Can now be written
1.5.teaspoons
```

- Before a recursion, ask yourself these questions:
    - What is the original question?
    - What is the recursive question?
    - What are the Terminal condition? (when the recursive stops)

### Handling null

- The `?` is used in Kotlin to handle null:

```kotlin
// The Rectangle? makes the function returns Rectangle or null
fun mayReturnRectangleOrNull() : Rectangle? { ... }

// With "?." the .rectangleMethod() will only occur when mayReturnRectangleOrNull() returns a rectangle
mayReturnRectangleOrNull()?.rectangleMethod() 

// Elvis ?: to have another value if the preceeding one return null
val somethingNotNull = emptyRectangle()
return mayReturnRectangleOrNull() ?: somethingNotNull 
```

- The `!!` to force the function to operate eventhough it can be null:

```kotlin
return if (list.isEmpty) -1 else list.min()!! //list can be null, without !! it would complain, but can still return null
```

- Using the `this@Class` inside of a `list.apply { this.prepend(this@Class) }`, you are calling the `this` of the class (so `this@Class` to differentiate from the other `this` (element of the list that you apply to).

### Work with recursive

When you have to create a recursive function, you first answer this three questions:
  - What is the original question: What you are actually trying to do?
  - What is the recursive question: What will you base your recursion on?
  - What are the terminal conditions: When should the recursive question stopped and return an answer?

## Keywords

- `Any` for any type
- `init {}` to check the values inputed at the creation of the class
- `override` at the beginning of the function to override it:

```kotlin
override fun equals(other: Any?) { ... }
```
- `operator` to override an operator function. Here an example with the comparison operator (`>`, `<`, ...)

```kotlin
operator fun compareTo(other: Probability) { ... }
```
- `infix` function are function where you can omit the `.`:

```kotlin
infix fun isCompatibleWith(other: Unit): Boolean { ... }

// calling the function using the infix notation
unit isCompatibleWith otherUnit

// is the same as
unit.isCompatibleWith(otherUnit)
```

- `typealias` is used to define a name for a function signature (hence alias) usually used to simplify simple functions into a type:
```kotlin
internal typealias CostStrategy = (Double) -> Double
```

### Operation on lists

- `flatMap` transforms a list of list of stuff into a simple list of stuff
```kotlin
list.flatMap { List<List<Path>> } // returns List<Path>
```

- `onEach` is the same as `list.map{ this.apply { ... } }`

- `sumByDouble` is the same as  `list.map{}.sum{}`