Instances of classes, structures, objects are first class citizens Functions are first class citizens Loops, method calls, conditionals Function calls Side-effects allowed in functions Pure functions
// private fields private final int id; private final int email; // public constructor public User(int id, String email){...} // Getters public int getId() {...} public String getEmail() {...} // No public setters ... }
// private fields private final int id; private final int email; // public constructor public User(int id, String email){...} // Getters public int getId() {...} public String getEmail() {...} // No public setters ... } // Immutable class in Kotlin class User(val id: Int, val email: String)
email: String) Classes are final by default in Kotlin. To make a class non-final, you have to use the “open” open class User(val id: Int, val email: String)
{ ... public User(int id, String email){...} // Getters public final int getId() {...} public final String getEmail() {...} } // Kotlin data class User( val id: Int, val email: String )
// Generated Java code public final class User { ... public User(int id, String email){...} // Getters public final int getId() {...} public final String getEmail() {...} public String toString() {...} public int hashCode() {...} public boolean equals(Object o) {...} ... }
... public final int component1() {...} public final String component2() {...} public final User copy(...) {...} } data class User( val id: Int, val email: String )
age: Int..) // Generated functions public final String component1() {...} // name public final int component2() {...} // age ... public final Type componentN() {...} //nth data class arg
something with result.value is Result.Error -> // do something with result.errorMessage } sealed class Result { class Success(val value: Any) : Result() class Error(val errorMessage: String) : Result() }
something with result.value is Result.Error -> // do something with result.errorMessage } But how does it work? sealed class Result { class Success(val value: Any) : Result() class Error(val errorMessage: String) : Result() }
class Success extends Result {...} public static final class Error extends Result {...} } // Kotlin sealed class Result { class Success(val value: Any) : Result() class Error(val errorMessage: String) : Result() }
{ if (Build.VERSION.SDK_INT >= Build.VERSION_CODES.O) { action() } } // Generated Java code public final void atLeastAndroidO(Function0 action) { if (VERSION.SDK_INT >= 26) { action.invoke(); } } Every lambda is an object. Not good for performance
Unit) {...} // Use like this fun doSomethingOnOreo() { atLeastAndroidO { println("Hey, running on O") } } method body is copied to the call-site // Generated code // Unused generated method void atLeastAndroidO(Function0 action) {...} void doSomethingOnOreo() { if (VERSION.SDK_INT >= 26) { System.out.println("Hey, running on O"); } }
index = 0 override fun hasNext() = index < childCount override fun next() = getChildAt(index++) override fun remove() = removeViewAt(--index) } Extension function on ViewGroup class!
own classes as well as other classes we don’t own. Operator overloading allows us to: Implemented by using the operator keyword //Example operator fun ViewGroup.iterator() ...
a-- operator fun plus(other: T) ...// a + b operator fun minus(other: T) ...// a - b operator fun get(index: Int) ...// a[i] operator fun contains(item: T) ...// a in b ... More examples:
< 27 class Fragment { ... final public FragmentActivity getActivity() { return mHost == null ? null : (FragmentActivity) mHost.getActivity(); } } // compiles ok but could throw an exception in runtime! activity.supportActionBar = ...
x: Double = 0.0, val y: Double = 0.0) // Kotlin class with @JvmOverloads class Point @JvmOverloads constructor(val label: String, val x: Double = 0.0, val y: Double = 0.0)
... companion object { val CREATOR: Parcelable.Creator<Data> = ... } } Compiler error. Documentation says: Classes implementing the Parcelable interface must also have a non-null static field called CREATOR of a type that implements the Parcelable.Creator interface.
25 person.name = "Oluwasegun" person.email = "[email protected]" person.cars = emptyList() // suggest to do this instead - it reads better val person = Person().apply { age = 25 name = "Oluwasegun" email = "[email protected]" cars = emptyList() }
responses to use Kotlin data classes • Convert interfaces from Java to Kotlin • Add tests in Kotlin • Gradually migrate the rest of the code base • Profit