PK - Chapter 4 Flashcards Preview

Kotlin 101 > PK - Chapter 4 > Flashcards

Flashcards in PK - Chapter 4 Deck (59):
1

Define a function "foo" with an Int parameter
and an Int return of the parameter squared.

fun foo(pInt: Int) = pInt * pInt

 

  • the Int return value is inferred by the compiler
  • can only be inferred for a single expression

2

Define a function "foo" with a String parameter
and a String return of the parameter contatenated
with "Hello World".

fun foo(pString: String) = "${pString} and Hello World"

3

What is a single expression function ?

  • Only has a single expression
  • does not need braces
  • does not need to specify the return type
  • uses the "=" sign rather than the "return" keyword

4

Describe member functions.

  • defined inside a class, object or interface
  • invoked using the name of the containing class,
    or object, with a dot notation
  • member functions can reference other functions
    in the object or class, with no additional syntax
  • member functions can access and modify member
    variables of the class

5

What is the DRY principle ?

Don't Repeat Yourself

6

Describe Local Functions.

  • also called nested functions
  • declared inside other functions
  • can be nested several times
  • not accessible to code outside the containing function
  • can access parameters and variables in the outer scope
  • does not need to define the parameters or variables in the outer scope

7

Use local functions inside a for loop
and when clause.

fun fizzBuzz(start: Int, end: Int) {
    for (k in start..end) {
        fun isFizz() = k % 3 == 0
        fun isBuzz() = k % 5 == 0
        when (
            isFizz() && isBuzz() -> println("Fizz Buzz")
            isFizz() -> println("Fizz")
            isBuzz() -> println("Buzz")
        }
    }
}

8

Explain top-level functions.

  • defined outside any class, object or interface
  • used to create standalone functions that do
    not belong to any object

9

What are the 4 types of functions ?

  • member functions
  • extension functions (special case of member function)
  • local functions
  • top-level functions

10

Explain named parameters.

  • when calling a function, the parameters can be named
  • explicit naming makes the intent clear
  • minimizes errors
  • not all parameters need to be names
  • once a parameter has been named, all subsequent
    parameters in the signature must be named
  • named parameters allow the order of parameters to
    be changed
  • cannot be used on Java-defined functions

11

Explain default parameters.

  • can be used to define functions and constructors
  • specified in the signature with the "=" sign
  • can omit parameters with a default
  • once a parameter is omitted, all subsequent
    parameters must be omitted, unless the
    parameters are named
  • default parameters, used with named parameters,
    is very powerful and eliminates bolierplate code
    for overrides
  • when overriding a function with default parameters,
    we must keep the same function signature

12

Explain extension functions.

  • enables you to create a new method on a class,
    without extending or wrapping it
  • you cannot override a function in the underlying class
    that has the same signature (name, parameters,
    order, return)

  • when defined as a top-level function in another file,
    it must be imported

13

Why create an extension function ?

  • frequently used to add a function to a final class,
    or a class in an SDK that you do not want to extend
  • avoids creating subclasses, or wrappers, which
    would require code changes to use the new class

14

Define extension function "bar{}"
for class "Foo".

fun Foo.bar() = "Foo Bar !"

15

Explain extension function precedence.

Extension function are resolved in the following order:

  • look for the method signature in the current receiver
  • look in the superclass(es)
  • look at the extension imports that are in scope

16

Create an extension function that handles nulls.

fun Any?.safeEquals(other: Any?): Boolean {
    if (this == null && other == null) return true
    if (this == null return false
    return this.equals(other)
}

17

What is a member extension function ?

Extension functions are usually declared at the top level.

A member extension function is defined inside a class.
Its scope is limited and no import is required.

18

Give an example of a mapping receiver
versus an extension receiver.

Extension receiver is an object of the class on
which the extension was defined and called.

A method in a class is called the dispatch receiver.

When there is shadowing of names, the extension receiver
will take precedence, so you must qualify the dispatch receiver.

private fun String.stringAdd() {
    map.put(this@ContainerClass.hashCode(), this)
}

19

Create a companion object extension.

fun Int.Companion.random() : Int {
    val random = Random()
    return random.nextInt()
}

val int = Int.random()

20

Explain the types; Pair and Triple.

These contain 2 and 3 identical types, respectively.

An example of Pair...

 

fun getPair() = Pair(getSomeInt(), getAnotherInt())

val (firstInt, secondInt) = getPair()

val myPair = "London" to "Paris"

21

Explain an infix function .

  • a function that is placed between 2 operands or arguments,
    so can only operate on 2 arguments
  • first argument is the instance that the function
    is invoked on
  • the second argument is an explicit parameter
    to the function

infix fun concat(other: String) = this + other

val myConcat = "Hello " concat "World!"

22

Explain operator overloading .

  • the ability to define functions that use operators
  • operators can only be defined as member functions
    or extension functions
  • can also be referenced with the dot notation and
    english label
  • can act on a different class than they are defined in
  • there is a fixed list of operators that can be used as
    functions, each with an English equivalent name

23

What is the list of basic operators
that can be overloaded ?

plus
minus
times
div
mod
rangeTo
unaryPlus
unaryMinus
not
 

24

What is the list of advanced operators
that can be overloaded ?

contains ( in )
get / set ( [ ] )
invoke (makes a class look like a function)
compareTo ( , <=, >= )

25

What is the list of assignment operators
that can be overloaded ?

These are a more restrictive operators that cannot
be used in conjunction with the basic operators:

plusAssign ( += )
minusAssign ( -= )
timesAssign ( *= )
divAssign ( /= )
modAssign ( %= )

26

Explain functional literals.

  • a variable (or val) can contain a function
  • the variable can be called just like a function,
    with the arguments in parenthesis
  • the assignment is made by enclosing the
    code in braces

val printMessage = { message: String -> println(message) }
...or since there is only a single parameter...
val printMessage = { println(it) }

printMessage("Hello World!")

27

Explain tail recursive functions.

A tail recursive function can be created if:

  • an invocation of a recursive function is the last operation
  • the result is simply to return the call

fun fact(k: Int) : Int {
    tailrec fun factTail(m: Int, n: Int) : Int {
        if (m == 0) return n
        else return factTail(m - 1, m * n)
    }
    return factTail(k, 1)
}

28

Explain varargs.

  • pass a comma-separated list of arguments, which
    is wrapped into an array
  • use the vararg argument before the parameter name
  • can only be one vararg per signature
  • must be the last argument, unless subsequent
    arguments are passed in using named parameters

29

Explain the spread operator.

If a function takes a vararg,
and you already have an array,
use the spread operator *

 

val strings = arrayOf("a", "b", "c")
doSomething("First Arg", *strings)

Future versions of Kotlin will support
collections other than arrays.

30

Name some of the more
common standard library functions.

  • apply
  • let
  • with
  • run
  • lazy
  • use
  • repeat
  • require / assert / check

31

What is a closure ?

A functional programming concept.
 

A function that has access to variables and
parameters defined in an outer scope.
 

It is said that they "close over" the variables
in the outer scope, hence the term closure.

32

Explain Any.apply.

  • accepts a lambda
  • the instance that the apply is called on
    is the lambda's receiver
  • used to create a builder pattern with an object
  • a standard library function, not a method of Any

 

val task = Runnable { println("Running!") }
Thread(task).apply { setDaemon(true) }.start()

33

Describe Any.apply( ?

  • Calls the specified lambda with `this` value
    as its receiver and returns `this` value.
  • Use it to create a builder pattern with any object.

 

val task = Runnable { println("Running") }
Thread(task).apply { setDaemon(true) }.start()

 

34

 Describe Any.let ?

  • Calls the specified closure as its argument
    and returns its result.
  • Creates a temporary variable "it" that can
    be used in the closure
  • Can still access the outer scope with "this"
  • A standard library function, not a method of Any

// need a better example
PrintWriter("myDocument.txt").let {
    it.append("$someVariable and some text\n")
    it.close()
}

35

What is the source code for Any.let ?

public inline fun T.let(block: (T) -> R): R {
    contract {
        callsInPlace(block, InvocationKind.EXACTLY_ONCE)
    }
    return block(this)
}

36

What is the source code for Any.apply ?

public inline fun T.apply(block: T.() -> Unit): T {
    contract {
        callsInPlace(block, InvocationKind.EXACTLY_ONCE)
    }
    block()
    return this
}

37

Describe Any.with(someObject).

  • Calls the specified closure with its argument
    as the current receiver

  • Enables you to call multiple functions on an
    object without repeating the receiver each time

  • A standard library function, not a method of Any

val g2: Graphics2D = ...
with(g2) {
    stroke = BasicStroke(10F)
    background = Color.BLACK
    ...
}

38

Describe Any.run .

  • combines the use cases of with and let
  • a closure is passed to run, which has the instance
    as its current receiver
  • the return value of the closure is the return value of run
  • a standard library function, not a method of Any

val outputPath = Paths.get("/usr/home").run {
    val path = resolve("output")
    path.toFile().createNewFile()
    path
}

39

Explain "it" versus "this".

  • "this" refers to the current receiver
  • "it" refers to a tighter scope temporary variable
    -  used by Any.also and Any.let amoung others
    -  used to reference a lambda's single, unnamed parameter
  • can use "it" in LINQ-style code:

strings.filter { it.length == 5 }.sortedBy { it }.map { it.toUpperCase() }

40

What is a higher-order function ?

A function that takes functions as
parameters, or returns a function.

interface Lock { ... }
fun   lock(lock: Lock, body: () -> T) : T {
    lock.lock()
    try {
        return body()
    }
    finally {
        lock.unlock()
    }
}

41

Explain the lazy keyword.

  • Wraps an expensive function call to be
    invoked once, when first required
  • synchronization is taken care of, eliminating
    race conditions or multiple requests

 

val lazyString = lazy { readStringFromDatabase() }

42

Explain the use of underscore "_" in lambdas.

Indicates an unused lambda parameter.

 

map.forEach { _, value -> println("$value") }

map.mapValues { (_, value) -> println("$value") }

 

Note the use of destructuring declaratios syntax
of the Pair in the second example

43

Explain the use keyword.

A more concise way of handling closeable
resources in simple cases.

  • an extension on an instance of closeable
  • accepts a function literal that operates on closeable
  • will safely invoke the function, closing down the
    resource afterward; whether or not the function
    completed successfully

val input = Files.newInputStream(Paths.get("input.txt"))
val byte = input.use( { input.read() } )
// the stream will be closed after the read

44

Explain the repeat keyword.

  • accepts a function literal and an integer
  • function will be invoked k times

 

repeat(howMany(), { println("Hello") } )

45

What are the
design by contract
keywords ?

Used to validate state at runtime

  • require
    assure arguments meet conditions
    throws IllegalArgumentException if not met
  • assert
    assure some logical condition
    throws AssertionException if not met
    can be disabled at runtime
  • check
    assure that internal state meets conditions
    throws IllegalStateException

46

Define a generic function "foo".

fun   printRepeat(whatToPrint: T, repeatCount: Int) {
    for (x in 0..repeatCount) {
        println(whatToPrint)
    }
}

 

Note that this could have been achieved with:

repeat(repeatCount, { println(whatToPrint) } )

47

Define a pure function.

  • deterministic (same output for same input)
  • does not create any side effects

 

Advantages:

  • can be cached
  • can be parallelized
  • can be tested in isolation

48

How does Kotlin leverage
Single Abstract Methods (SAMs)
implemented in Java.

  • SAM is a Java interface that defines a single method
  • there are many of these in the Java standard library
  • Kotlin can convert a function literal into a SAM

val threadPool = Executors.newThreadPool(4)
threadPool.submit { println("Hello World!") }

49

How do you handle keyword conflicts
between Java and Kotlin ?

Wrap the conflicting keyword in backticks.

 

var myDate: Date = ...
myDate.`when`("2016")

50

How does Kotlin handle
checked methods in Java ?

Kotlin does not have checked exceptions.

Java methods with checked exceptions are
treated the same as methods that do not.

51

How are Java void methods
handled in Kotlin ?

Treated as a function
returning Unit.

52

How do you use
top-level functions from Java ?

  • The functions are defined as Java static methods
    in a class with the name of the package by default
  • the @file:JvmName("MyClassName") annotation
    will instead create a class named MyClassName
    for top-level functions in this file
  • the @file:JvmMultifileClass("MyClassName") annotation
    can create a class that is used for all top-level functions
    in the package

@file:JvmName("MyUtils")
package com.company.somepackage
fun cube(n: Int) : Int = n * n * n

53

How can Java use a Kotlin
function with default parameters ?

Use the @JvmOverloads annotation to
generate all the overloaded methods for Java.

 

@JvmOverloads fun foo(firstArg: String = "Hello", secondArg: String = "World") { }

54

Explain Any.takeIf and Any.takeUnless.

  • takeif 
    Returns `this` value if it satisfies the given [predicate] else `null`
  • takeUnless
    Returns `this` value if it does NOT satisfy the given [predicate] else `null`
  • called on the object, so good for chaining
  • standard library functions, not methods on Any

 

someObject?.takeIf{ booleanPredicate }?.apply { doThis() }

55

Summarize the following
standard library functions:

  • apply
  • also
  • run
  • let

Defining attributes:

  • current receiver
  • builder / mapper

 

A image thumb
56

57

What is a
Single Abstract Method (SAM) ?

  • an interface that defines a
    single method
  • only for interfaces implemented
    ​in Java
  • SAMs occur frequently in the
    Java standard library
  • you can pass a function literal
    where a SAM is expected

val threadPool = Executors.newFixedThreadPool(4)
threadPool.submit { println("Working hard!") }

58

Create a
named companion object
named "Foo" and call
its methods from Java
and Kotlin.

  • often used to create singletons
  • can use @JvmStatic to make the
    someMethod() static


object Foo {
    fun someMethod() { doSomething() }
}

// from Java
Foo.INSTANCE.someMethod()

// from Kotlin
Foo.someMethod()

59

How do you throw an exception
from Kotlin to Java ?

  • Java only catches checked exceptions,
    but there are no checked exceptions in
    Kotlin
  • use the @Throws annotation to add the
    exception to the JVM method signature
    for Java

@Throws(IOException::class)
fun createDirectory(file: File) {
    // throw IOException
}