Kotlin Basics: Syntax, Classes, Objects, and Functions with Examples
This article provides a comprehensive Kotlin tutorial for Android developers, covering basic syntax, variable declarations, control statements, functions, classes, objects, delegation, and standard library utilities, illustrated with clear code examples and explanations.
Preface: Kotlin is a new choice for Android development, offering concise syntax, safety, and functional programming features that make it very convenient in real projects.
1. Basic Syntax
1.1 Variable Declaration
Kotlin uses var for mutable variables and val for read‑only variables. The compiler can infer the variable type from the assigned value, which is called automatic type inference; declaring without an explicit type is an implicit declaration.
/** * Student class */
class Student {
// mutable variable declaration keyword var
var name: String = "小明"
// implicit type declaration without specifying the type
var age = 10
// read‑only variable declaration keyword val
val sex: String = "男"
fun learn() {
print("$name is learning")
}
}1.2 Statements
when expression
The when statement can be used as an expression; the branch that matches becomes the value of the whole expression.
val b = when (num) {
in 0..9 -> true
else -> false
}in keyword usage
The in keyword checks whether a value lies within a range, and can also be used in for loops to iterate over collections.
// check if within range
if (num in 1..9) {
print("ok")
}
// not in range
if (num !in 1..9) {
print("no")
}
// iterate over array
for (name in names) {
print(name)
}
// check if element is in array
if (name in names) {
print("ok")
}Type conversion
Kotlin uses the is keyword for type checking. After a successful check, the variable is automatically cast to the checked type.
fun foo(o: Any): Int {
if (o is String) {
// o is automatically cast to String
return o.length
}
if (o !is String) {
return 0
}
return 0
}Null‑safety
Kotlin uses the ? operator for safe calls; for example, str?.length evaluates the length only when str is not null, preventing NullPointerException.
1.3 Function Declaration
A simple function is declared with the fun keyword.
fun plus(x: Int, y: Int): Int {
return x + y
}The function returns an Int value. The fun keyword introduces the function, and the signature follows the pattern fun name(params): ReturnType.
1.4 Default Parameters
Kotlin allows default values for parameters, reducing the need for overloads.
fun plus(x: Int, y: Int = 10): Int {
return x + y
}Calling plus(11, 20) uses the supplied y, while plus(11) uses the default value 10.
1.5 Varargs
Java uses ... for varargs; Kotlin uses the vararg keyword.
// Java varargs
public void selectCourse(String... strArray) { }
// Kotlin varargs
fun selectCourse(vararg strArray: String?) { }2. Classes and Objects
2.1 Constructors
Kotlin classes can have a primary constructor and one or more secondary constructors. The primary constructor is part of the class header and can omit the constructor keyword when there are no annotations or visibility modifiers.
class Person constructor(name: String) {
init {
// initialization code
}
// secondary constructor delegating to primary
constructor(name: String, parent: Person) : this(name) {}
// another secondary constructor delegating to the previous one
constructor(name: String, parent: Person, age: Int) : this(name, parent) {}
}2.2 Inheritance
All Kotlin classes inherit from Any, which provides equals(), hashCode(), and toString(). A derived class must call the base class constructor if the base has a primary constructor.
class Derived(p: Int) : Base(p) {}If the derived class has no primary constructor, each secondary constructor must initialize the base type using super or delegate to another constructor.
class MyView : View {
constructor(ctx: Context) : super(ctx)
constructor(ctx: Context, attrs: AttributeSet) : super(ctx, attrs)
}2.3 Properties
Getter and Setter
Properties automatically generate getters; val generates only a getter, while var generates both getter and setter. Custom getters and setters can be defined.
var age: Int = 11
get() { return field }
set(value) { field = value + 1 }Backing Field
Using field inside a custom accessor accesses the automatically generated backing field. Without a proper backing field, recursive calls can cause a stack overflow.
class Person {
var name = ""
set(value) { field = value }
}Constants
Constants can be declared with const val or with the @JvmField annotation to suppress the generation of a getter.
class Person {
companion object {
const val TAG = "Person"
}
@JvmField
val TAG = "Person"
}Late‑init Properties
Properties declared with lateinit can be initialized later; accessing them before initialization throws an exception.
2.4 Inner Classes
By default, nested classes are static. Adding the inner modifier makes the class non‑static and allows it to access members of the outer class.
class Outer {
private val b: Int = 1
inner class Inner {
fun foo(): Int = b
}
}
val d = Outer().Inner().foo() // == 12.5 Data Classes
Data classes are declared with the data keyword and must have at least one val or var parameter in the primary constructor. They automatically generate toString(), equals(), hashCode(), and copy().
data class Person(val name: String) {
var age: Int = 0
}
fun foo() {
val person1 = Person("John")
val person2 = Person("John")
person1.age = 10
person2.age = 20
// person1 and person2 are considered equal despite different ages
person1.equals(person2) // true
}2.6 Enum Classes
Each enum constant is an object. Enum classes can have properties, methods, and abstract methods that each constant must implement.
enum class Direction { NORTH, SOUTH, WEST, EAST }
enum class Color(val rgb: Int) {
RED(0xFF0000) {
override fun print() { print("red") }
},
GREEN(0x00FF00) {
override fun print() { print("green") }
},
BLUE(0x0000FF) {
override fun print() { print("blue") }
};
abstract fun print()
}
fun main() { Color.BLUE.print() }2.7 Delegation
Class Delegation
Delegation can be implemented with the by keyword.
// interface
interface Base { fun print() }
// class that implements the interface
class BaseImpl(val x: Int) : Base {
override fun print() { print(x) }
}
// delegate class
class Agent(b: Base) : Base by b
fun main(args: Array<String>) {
val b = BaseImpl(1)
Agent(b).print() // prints 1
}Property Delegation
Property delegation is achieved by providing a delegate object that defines getValue and setValue operators.
class Delegate {
operator fun getValue(thisRef: Any?, property: KProperty<*>): String {
return "thank you for delegating '${property.name}' to me"
}
operator fun setValue(thisRef: Any?, property: KProperty<*>, value: String) {
print("$value has been assigned to '${property.name}'")
}
}
class Example {
var p: String by Delegate()
}
fun foo() {
val e = Example()
print(e.p) // prints thank you ...
e.p = "new" // prints assignment message
}Standard Delegates
Lazy: val lazyStr: String by lazy { "123" } Not‑null: var name: String by Delegates.notNull() Observable:
var name: String by Delegates.observable("old") { prop, old, new -> print("${prop.name} changed: $old -> $new") }3. Functions
3.1 Local Functions
Kotlin allows functions to be defined inside other functions; the inner function can access variables from the outer scope (closure).
fun outer(str: String) {
fun inner(index: Int) {
str.substring(0, index)
}
inner(2)
}3.2 Function Types
Function types are expressed as (A, B) -> C. They can also have a receiver type, e.g., A.(B) -> C. Suspend functions are prefixed with suspend.
// (A, B) -> C
val fun1: (String, String) -> Unit = { s1, s2 ->
print("$s1 and $s2")
}
// A.(B) -> C
val fun2: String.(String) -> Unit = { s ->
print("$this $s")
}3.3 Lambda Expressions
Lambdas are written inside curly braces; parameters are declared before the -> arrow.
val sum = { x: Int, y: Int -> x + y }Trailing lambda syntax allows the lambda to be placed outside the parentheses when it is the last argument.
fun sum(m: Int, n: Int, param: (Int, Int) -> Int): Int {
return param.invoke(m, n)
}
fun main(args: Array<String>) {
sum(1, 2) { x, y -> x + y }
}3.4 Anonymous Functions
Anonymous functions are similar to lambdas but allow an explicit return type.
fun(x: Int, y: Int): Int = x + y3.5 Higher‑Order Functions
Functions that take other functions as parameters or return them are called higher‑order functions.
fun sum(m: Int, n: Int, param: (Int, Int) -> Int): Int {
return param.invoke(m, n)
}3.6 Infix Notation
Functions marked with infix can be called using infix notation.
infix fun Int.sum(x: Int): Int { return this + x }
fun main(args: Array<String>) {
1 sum 2 // equivalent to 1.sum(2)
}3.7 Inline Functions
Marking a function with inline causes the compiler to inline the function body and any lambda arguments, eliminating the overhead of function objects and virtual calls.
inline fun show(str: String) { print(str) }
fun main(args: Array<String>) {
print("start")
show("123")
print("end")
}Without inline, the call to show remains a regular method call.
3.8 Standard Library Functions
Function
Definition
Purpose
run
public inline fun run (block: () -> R): R = block()
Executes the block and returns its last expression.
apply
public inline fun T.apply (block: T.() -> Unit): T { block(); return this }
Runs a block with this as the receiver and returns the object.
let
public inline fun T.let (block: (T) -> R): R = block(this)
Passes the object as an argument ( it) to the block and returns the block result.
also
public inline fun T.also (block: (T) -> Unit): T { block(this); return this }
Similar to let but returns the original object.
with
public inline fun with (receiver: T, block: T.() -> R): R = receiver.block()
Calls a block with the given receiver as this and returns the block result.
Summary
The article presents a practical overview of Kotlin fundamentals across three areas: basic syntax, class/object features, and function capabilities. Understanding functions—Kotlin's first‑class citizens—is especially important, as they enable concise and expressive code that can greatly improve development efficiency.
Signed-in readers can open the original source through BestHub's protected redirect.
This article has been distilled and summarized from source material, then republished for learning and reference. If you believe it infringes your rights, please contactand we will review it promptly.
Sohu Tech Products
A knowledge-sharing platform for Sohu's technology products. As a leading Chinese internet brand with media, video, search, and gaming services and over 700 million users, Sohu continuously drives tech innovation and practice. We’ll share practical insights and tech news here.
How this landed with the community
Was this worth your time?
0 Comments
Thoughtful readers leave field notes, pushback, and hard-won operational detail here.
