kotlin

created : 2022-12-22T16:53:21+00:00
modified : 2022-12-31T10:13:09+00:00

kotlin

Variable

val answer: Int = 42 // value
var answer: Int = 42 // variable
fun main(args: Array<String>) {
  val name = if (args.size > 0) args[0] else "Kotlin"
  println("Hello, $name!")
}
class Person(
  val name: String,
  var isMarried: Boolean
)

val person = Person("Bob", true)
class Rectangle(val height: Int, val width: Int) {
  val isSquared: Boolean
    get() {
      return height == width
    }
}
enum class Color {
  RED, ORANGE, YELLOW
}

enum class Color(
  val r: Int, val g: Int, val b: Int
) {
  RED(255, 0, 0),
  ORANGE(255, 165, 0),
  YELLOW(255, 255, 0)

  fun rgb() = (r * 256 + g) * 256 + b
}
fun mix(c1: Color, c2: Color) =
  when (setOf(c1, c2)) {
    setOf(RED, YELLOW) -> ORANGE
    setOf(YELLOW, BLUE) -> GREEN
    else -> throw Exception("Dirty color")
  }
interface Expr
class Num(val value: Int) : Expr
class Sum(val left: Expr, val right: Expr) : Expr

fun eval(e: Expr) : Int =
  when (e) {
    is Num -> e.value
    is Sum -> eval(e.right) + eval(e.left)
    else -> throw IllegalArgumentException("Unknown expression")
  }
for (i in 1..100) {
  println(i)
}
val binaryReps = TreeMap<Char, String>()
for (c in 'A'..'F') {
  val binary = Integer.toBinaryString(c.toInt())
  binaryReps[c] = binary
}

for ((letter, binary) in binaryReps) {
  println("$ltter = $binary")
}
for isLetter(c: Char) = c in 'a'..'z' || c in 'A'..'Z'
println(isLetter('q'))
fun readNumber(reader: BufferdReader): Int? {
  try {
    val line = reader.readLine()
    return Integer.parseInt(line)
  } catch (e: NumberFormatException) {
    return null
  } finally {
    reter.close()
  }
}
fun <T> joinToString(
  collection: Collection<T>,
  separator: String = ", ",
  prefix: String = "",
  postfix: String = ""
): String
const val UNIX_LINE_SEPARATOR = "\n"
// public static final String UNIX_LINE_SEPARATOR = "\n";
fun String.lastChar(): Char = get(length - 1)
interface Clickable {
  fun click()
  fun showOff() = println("I'm clickable!")
}

interface Focusable {
  fun setFocus(b: Boolean) =
    println("I $if (b) "got" else "lost"} focus.")
  fun showOff() = println("I'm focusable!")
}

class Button: Clickable, Focusable {
  override fun click() = println("I was clicked")
  override fun showOff() {
    super<Clickable>.showOff()
    super<Focusable>.showOff()
  }
}
sealed class Expr {
  class Num(val value: Int) : Expr()
  class Sum(val left: Expr, val right: Expr) : Expr()
}

fun eval(e: Expr): Int =
  when (e) {
    is Expr.Num -> e.value
    is Expr.Sum -> eval(e.right) + eval(e.left)
  }
class User constructor(_nickname: String) {
  val nickname: String
  init {
    nickname = _nickname
  }
}

class User (_nickname: String) {
  val nickname = _nickname
}

class User(val nickname: String)

class User(val nickname: String,
           val isSubscribed: Boolean = true)

open class User(val nickname: String) { ... }
class TwitterUser(nickname: String) : User(nickname) { ... }
open class View {
  constructor(ctx: Context) {
    // code
  }

  constructor(ctx: Context, attr: AttributeSet) {
    // code
  }
}

class MyButton : View {
  constructor(ctx: Context)
    : this(ctx, MY_STYLE) {
    // code
  }

  constructor(ctx: Context, attr: AttributeSet)
    : super(ctx, attr) {
    // code
  }
}
class Client(val name: String, val postalCode: Int) {
  override fun equals(other: Any?): Boolean {
    if (other == null || other !is Client)
      return false
    return name == other.name &&
      postalCode == other.postalCode
  }
  override fun hashCode(): Int = name.hashCode() * 31 + postalCode
}
val client1 = Client("John", 4122)
val client2 = Client("John", 4122)

println(client1 == client2) // true (called equals)
println(client1 === client2) // false
class DelegatingCollection<T> (
  innerList: Collection<T> = ArrayList<T>()
) : Collection<T> by innerList {}
class CountingSet<T>(
  val innerSet: MutableCollection<T> = HashSet<T>()
) : MutableCollection<T> by innerSet {
  var objectsAdded = 0
  override fun add(element: T): Boolean {
    objectsAdded++
    return innserSet.add(element)
  }

  override fun addAll(c: Collection<T>): Boolean {
    objectsAdded += c.size
    return innerSet.addAll(c)
  }
}
object CaseInsenitiveFileComparator: Comparator<File> {
  override fun compare(file1: File, file2: File): Int {
    return file1.path.compareTo(file2.path,
      ignoreCase = true)
  }
}

println(CaseInsensitiveFileComparator.compare(
  File("/User"),
  File("/user")
))
class A {
  companion object {
    fun bar() {
      println("Companion object called")
    }
  }
}
A.bar()
class User private consturctor(val nickname: String) {
  companion object {
    fun newSubscribingUser(email: String) =
      User(email.substringBefore('@'))
    fun newFacebookUser(accountId: Int) =
      User(getFacebookName(accountId))
  }
}
class Person(val name: String) {
  companion object Loader {
    fun fromJSON(jsonText: String): Person = ...
  }
}

person = Person.Loader.fromJSON("{name: 'Dmitry'}")
val sum = { x: Int, y: Int -> x + y }
println(sum(1, 2)) // 3
val people = listOf(Person("Alice", 29), Person("bob", 31))
println(people.maxBy() { p: Person -> p.age })
println(people.maxBy({ p: Person -> p.age })
println(people.maxBy { p: Person -> p.age })
println(people.maxBy { it.age })
val list = listOf(1, 2, 3, 4)
println(list.filter { it % 2 == 0 })
println(list.map { it * it })
val canBeInClub27 = { p: Person -> p.age <= 27 }
val people = listOf(Person("Alice", 27), Person("Bob", 31))
println(people.all(canBeInClub27)) // false
println(people.any(canBeInClub27)) // true
println(peopl.count(canBeInClub27)) // 1
println(people.find(canBeInClub27)) // Person(name=Alice, age=27)
println(people.groupBy { it. age })
// {29=[Person(name=Bob, age=29)], 31=[Person(name=Alice, age=31)]}
val strings = listOf("abc", "def")
println(strings.flatMap { it.toList() })
// [a, b, c, d, e, f]
people.asSequence()
  .map(Person::name)
  .filter { it.startsWith("A") }
  .toList()
fun alphabet(): String {
  val stringBuilder = StringBuilder()
  return with(stringBuilder) {
    for (letter in 'A'..'Z') {
      this.append(letter)
    }
    append("\nNow I know the alphabet!")
    this.toString()
  }
}

fun alphabet() = StringBuilder().apply {
  for (letter in 'A'..'Z') {
    append("letter")
  }
  append("\nNow I know the alphabet!")
}.toString()
fun strLenSafe(s: String?): Int =
  if (s != null) s.length else 0
fun printAllCaps(s: String?) {
  val allCaps: String? = s?.toUpperCase()
  println(allCaps)
}
class Address(val streetAddress: String, val zipCode: Int,
             val city: String, vall country: String)
class Company(val name: String, val address: Address?)
class Person(val name: String, val company: Company?)
fun Person.countryName(): String {
  val country = this.company?.address?.country
  return if (country != null) country else "Unknown"
}
fun foo(s: String?) {
  val t: String = s ?: ""
}
class Person(val firstName: String, val lastName: String) {
  override fun equals(o: Any?): Boolean {
    val otherPerson = o as? Person ?: return false
    return otherPerson.firstName == firstName &&
           otherPerson.lastName == lastName
  }

  override fun hashCode(): Int =
    firstName.hashCode() * 37 + lastName.hashCode()
}
fun ignoreNulls(s: String?) {
  val sNotNull: String = s!!
  println(sNotNull.length)
}
fun sendEmailTo(email: String) {
  println("Sending email to $email")
}
var email: String? = "yole@example.com"
email?.let { sendEmailTo(it) }
fun <T> printHashCode(t: T) {
  println(t?.hashCode())
}
printHashCode(null) // T = Any?
interface Processor<T> {
  fun process(): T
}
class NoResultProcessor: Processor<Unit> {
  override fun process(0 {
    // does not need to return
  })
}
fun fail(message: String): Nothgin {
  throw IllegalStateException(message)
}
fun <T> copyElements(source: Collection<T>,
                     target: MutableCollection<T>) {
  for (item in source) {
    target.add(item)
  }
}
  • List : listOf : mutableListOf, arrayListOf
  • Set : setOf : mutableSetOf, hashSetOf, linkedSetOf, sortedSetOf
  • Map : mapOf : mutableMapOf, hashMapOf, linkedMapOf, sortedMapOf
data class Point(val x: Int, val y: Int) {
  operator fun plus(other: Point): Point {
    return Point(x + other.x, y + other.y)
  }
}

val p1 = Point(10, 20)
val p2 = Point(30, 40)
println(p1 + p2) // Point(x=40, y=60)
operator fun <T> MutableCollection<T>.plusAssign(element: T) {
  this.add(element)
}
operator fun Point.unaryMinus(): Point {
  return Point(-x, -y)
}
val p = Point(10, 20)
println(-p)
class Person(
  val firstName: String, val lastName: String
) : Comparable<Person> {
  override fun compareTo(other: Person): Int {
    return compareValuesBy(this, other,
      Person::lastName, Person::firstName)
  }
}

val p1 = Person("Alice", "Smith")
val p2 = Person("Bob", "Johnson")
println(p1 < p2)
operator fun Point.get(index: Int): Int {
  return when(index) {
    0 -> x
    1 -> y
    else ->
      throw IndexOutOfBoundsException("Invalid coordinate $index")
  }
}
val p = Point(10, 20)
println(p[1])
data class MutablePoint(var x: Int, var y: Int)
operator fun MutablePoint.set(index: Index, value: Int) {
  when(index) {
    0 -> x = value
    1 -> y = value
    else ->
      throw IndexOutOfBoundsException("Invalid coordinate $index")
  }
}
val p = MutablePoint(10, 20)
p[1] = 42
data class Rectangle(val upperLeft: Point, val lowerRight: Point)
operator fun Rectangle.contains(p: Point): Boolean {
  return p.x in upperLeft.x until lowerRight.x &&
    p.y in upperLeft.y until lowerRight.y
}
val rect = Rectangle(Point(10, 20), Point(50, 50))
println(Point(20, 30) in rect)
// operator fun <T: Comparable<T>> T.rangeTo(that: T): ClosedRange<T>
val now = LocalDate.now()
val vacation = now..now.plusDays(10)
println(now.plusWeeks(1) in vacation)
operator fun ClosedRange<LocalDate>.iterator(): Iterator<LocalDate> =
  object : Iterator<LocalDate> {
    val current = state
    override fun hasNext() =
      current <= endInclusive
    override fun next() = current.apply {
      current = plusDays(1)
    }
  }

val newYear = LocalDate.ofYearDay(2017, 1)
val daysOff = newYear.minusDays(1)..newYear
for (dayOff in daysOff) { println(dayOff) }
// 2016-12-31
// 2017-01-01
val p = Point(10, 20)
val (x, y) = p
// val a = p.component1()
// val b = p.component2()

class Point(val x: Int, val y: Int) {
  operator fun component1() = x
  operator fun component2() = y
}
class Foo {
  var p: Type by Delegate()
}
class Person(val name: String) {
  private var _emails: List<Email>? = null
  val emails: List<Email>
    get() {
      if (_emails == null) {
        _emails = loadEmails(this)
      }
      return _emails!!
    }
}

class Person(val name: String) {
  val emails by lazy { loadEmails(this) }
}
fun twoAndThree(operation: (Int, Int) -> Int) {
  val result = operation(2, 3)
  println("The result is $result")
}
inline fun<T> synchronized(lock: Lock, action: () -> T): T {
  lock.lock()
  try {
    return action()
  }
  finally {
    lock.unlock()
  }
}

val l = lock()
synchronized(l) {
  // do something
}
fun lookForAlice(people: List<Person>) {
  people.forEach label@{
    if (it.name == "Alice") return@label
  }
  println("Alice might be somewhere")
}
val <T> List<T>.penultimate: T
  get() = this[size - 2]
class Processor<T> {
  fun process(value: T) {
    value?.hashCode() // value is nullable
  }
}

class Processor<T: Any> {
  fun process(value: T) {
    value.hashCode() // value is not nullable
  }
}
if (value is List<*>) { ... }
fun printSum(c: Collection<Int>) {
  if (c is List<Int>) {
    println(c.sum())
  }
}
inline fun<reified> isA(value: Any) = value is T
println(isA<String>("abc") // true
println(isA<String>(123))  // false
open class Animal {
  fun feed() { ... }
}

class Herd<T: Animal> {
  val size: Int get() = ...
  operator fun get(i: Int): T { ... }
}

fun feedAll(animals: Herd<Animal>) {
  for (i in 0 until animals.size) {
    animals[i].feed()
  }
}
interface FieldValidator<in T> {
  fun validate(input: T): Boolean
}

object DefaultStringValidator: FieldValidator<String> {
  override fun validate(input: String) = input.isNotEmpty()
}

object DefaultIntValidator : FieldValidator<Int> {
  override fun validate(input: Int) = input >= 0
}
class HasTempFolder {
  @get:Rule
  val folder = TemporaryFolder()

  @Test
  fun testUsingTempFolder() {
    val createdFile = folder.newFile("myfile.text")
    ...
  }
}
  • property, field, get, set, receiver, param, setparam, delegate, file
data class Person(
  @JsonName("alias") val firstName: String,
  @JsonExclude val age: Int? = null
)
class Person(val name: String, val age: Int)
val kClass = person.javaClass.kotlin // KClass<Person>
println(kClass.simpleName) // Person
kClass.memberProperties.forEach { println(it.name) }
// age
// name