Created by Todd Ginsberg 
						for CJUG
						
						
					    2016-12-13
					
The Gateway to St. Petersburg!
 
					Photo courtesy of Wikimapia
class Customer(name: String) {
    init {
        println("Customer initialized with value ${name}")
    }
    ...
}
						
open class Entity(name: String) { 
	...
}
class Customer(name: String) : Entity(name) {
    init {
        println("Customer initialized with value ${name}")
    }
    ...
}
						
var name: String = "Todd" // Initial
name = "Emma"             // OK
						
val name: String = "Todd" // Initial
name = "Emma"             // Compiler Error
						
val s1 = "CJUG"
val s2 = "cjug"
s1 == s2.toUpperCase()  // (Structural) True!
s1 === s2               // (Referential) False
						
val me: Person = Person("Todd")
						
val status: String = if(x == 42) "Success" else "Fail"
						Use if expression instead!
fun generateRandomNumber(): Int {
    return 4
}
						
fun generateRandomNumber(): Int = 4
						
fun generateRandomNumber(start: Int = 0): Int = start + 4
						
generateRandomNumber()    // 4
generateRandomNumber(1)   // 5
generateRandomNumber(start = 1)   // 5
						Can't Someone Else Do It?
var result : Int = add(1, 1)
fun negate(number: Int): Int = 0-number
						
var result = add(1, 1) 
fun negate(number: Int) = 0-number 
						No need to cast
when (x) {
    is Int -> print(x % 2 == 0)
    is String -> print(x.length + 1)
    is IntArray -> print(x.sum())
}
						
var name : String = "Todd" // Guaranteed to never be null
var salary : Int? = null   // May be null
						
var homeTown : String? = null
println(homeTown.toUpperCase())  // Not allowed
						
val homeTown : String? = ...
println(homeTown?.toUpperCase()) // OK!
                ^^
						
val lowest : Int? = listOf(1, 2, 3).min()
						
val lowest : Int = listOf(1, 2, 3).min() ?: 0
						
val homeTown : String? = ...
println(homeTown?.toUpperCase() ?: "Unknown")
						
val lowest : Int? = listOf(1, 2, 3).min()
						
val lowest : Int = listOf(1, 2, 3).min()!!
						
val lowest : Int = listOf<Int>().min()!!
// KotlinNullPointerException!
						Extend existing types with your own functions!
fun String.initialCaps(): String =
    when(this.length) {
        0 ->    this
        1 ->    this.toUpperCase()
        else -> this[0].toUpperCase() + this.substring(1).toLowerCase()
    }
						Pssst! Hey, 'when' is an expression returning a value!
listOf(2,3,4).map { a -> a * 2 } // [4,6,8]
						
listOf(2,3,4).map { it * 2 } // [4,6,8]
						
var sum = 0
ints.filter { it > 0 }.forEach {
    sum += it
}
print(sum)
						Can access variables in their outer scope
class Person() {
    var name: String? = null
}
						
val e = Person()
e.name = "emma"
println("Person's name is ${e.name}")
// -> "Person's name is emma"
						
class Person() {
    var name: String? = null
        set(value) {
            field = value?.initialCaps() ?: value
        }
}
val e = Person()
e.name = "emma"
println("Person's name is ${e.name}")
// -> "Person's name is Emma"
						
class Customer(val name: String) {
    ...
}
						Java version...
public class PersonDto {
    public String firstName;
    public String lastName;
}
						Still Java Version
public String getFirstName() {
    return firstName;
}
public void setFirstName(final String firstName) {
    this.firstName = firstName;
}
public String getLastName() {
    return lastName;
}
public void setLastName(final String lastName) {
    this.lastName = lastName;
}
						Even More Java Version
@Override
public String toString() {
    return "PersonDto{" +
            "firstName='" + firstName + '\'' +
            ", lastName='" + lastName + '\'' +
            '}';
}
						Even Yet Still More Java Version
@Override
public boolean equals(Object o) {
    if (this == o) {
        return true;
    }
    if (o == null || getClass() != o.getClass()) {
        return false;
    }
    PersonDto personDto = (PersonDto) o;
    if (!firstName.equals(personDto.firstName)) {
        return false;
    }
    return lastName.equals(personDto.lastName);
}
						Oh come on...
@Override
public int hashCode() {
    int result = firstName.hashCode();
    result = 31 * result + lastName.hashCode();
    return result;
}
						
data class PersonDto(var firstName: String, var lastName: String)