3-Classes and Objects
3-Classes and Objects
Luca Verderame
About this lesson
Lesson 3: Classes and objects
○ Classes
○ Inheritance
○ Extension functions
○ Special classes
○ Organizing your code
○ Summary
2
Classes
3
Class
Object
● Classes are blueprints for objects
instances
● Classes define methods that operate
on their object instances
Class
4
Class versus object instance
House Class Object Instances
Data
● House color (String)
● Number of windows (Int)
● Is for sale (Boolean)
Behavior
● updateColor()
● putOnSale() FOR SALE
5
Define and use a class
Class Definition Create New Object Instance
6
Constructors
When a constructor is defined in the class header, it can contain:
● No parameters
class A
● Parameters
○ Not marked with var or val → copy exists only within scope of the
constructor
class B(x: Int)
○ Marked var or val → copy exists in all instances of the class
class C(val y: Int)
7
Constructor examples
class A val aa = A()
8
Default parameters
Class instances can have default values.
● Use default values to reduce the number of constructors needed
● Default parameters can be mixed with required parameters
● More concise (don’t need to have multiple constructor versions)
class Box(val length: Int, val width:Int = 20, val height:Int = 40)
val box1 = Box(100, 20, 40)
val box2 = Box(length = 100)
val box3 = Box(length = 100, width = 20, height = 40)
9
Primary constructor
Declare the primary constructor within the class header.
class Circle(i: Int) {
init {
...
}
}
This is technically equivalent to:
class Circle {
constructor(i: Int) {
...
}
}
10
Initializer block
● Any required initialization code is run in a special init block
● Multiple init blocks are allowed
● init blocks become the body of the primary constructor
11
Initializer block example
Use the init keyword:
val s = Square(10)
=> 20
12
Multiple constructors
● Use the constructor keyword to define secondary constructors
● Secondary constructors must call:
○ The primary constructor using this keyword
OR
○ Another secondary constructor that calls the primary constructor
13
Multiple constructors example
class Circle(val radius:Double) {
constructor(name:String) : this(1.0)
constructor(diameter:Int) : this(diameter / 2.0) {
println("in diameter constructor")
}
init {
println("Area: ${Math.PI * radius * radius}")
}
}
val c = Circle(3)
14
Properties
● Define properties in a class using val or var
● Access these properties using
dot . notation with property name
● Set these properties using
dot . notation with property name (only if declared a var)
15
Person class with name property
class Person(var name: String)
fun main() {
val person = Person("Alex")
println(person.name) Access with .<property name>
person.name = "Joey" Set with .<property name>
println(person.name)
}
16
Custom getters and setters
If you don’t want the default get/set behavior:
17
Custom getter
class Person(val firstName: String, val lastName:String) {
val fullName:String
get() {
return "$firstName $lastName"
}
}
18
Custom setter
var fullName:String = ""
get() = "$firstName $lastName"
set(value) {
val components = value.split(" ")
firstName = components[0]
lastName = components[1]
field = value
}
19
Member functions
● Classes can also contain functions
● Declare functions as shown in Functions in Lesson 2
○ fun keyword
○ Can have default or required parameters
○ Specify return type (if not Unit)
20
Inheritance
21
Inheritance
● Kotlin has single-parent class inheritance
● Each class has exactly one parent class, called a superclass
● Each subclass inherits all members of its superclass
including ones that the superclass itself has inherited
If you don't want to be limited by only inheriting a single class, you can define an
interface since you can implement as many of those as you want.
22
Interfaces
● Provide a contract all implementing classes must adhere to
23
Interface example
interface Shape {
fun computeArea() : Double
}
class Circle(val radius:Double) : Shape {
override fun computeArea() = Math.PI * radius * radius
}
val c = Circle(3.0)
println(c.computeArea())
=> 28.274333882308138
24
Extending classes
To extend a class:
● Create a new class that uses an existing class as its core
(subclass)
● Add functionality to a class without creating a new one
(extension functions)
25
Creating a new class
26
Classes are final by default
Declare a class
class A
Try to subclass A
class B : A
27
Use open keyword
Use open to declare a class so that it can be subclassed.
Declare a class
open class C
Subclass from C
class D : C()
28
Overriding
● Must use open for properties and methods that can be overridden
(otherwise you get compiler error)
29
Abstract classes
● Class is marked as abstract
● Cannot be instantiated, must be subclassed
● Similar to an interface with the added the ability to store state
● Properties and functions marked with abstract must be
overridden
● Can include non-abstract properties and functions
30
Example abstract classes
abstract class Food {
abstract val kcal : Int
abstract val name : String
fun consume() = println("I'm eating ${name}")
}
class Pizza() : Food() {
override val kcal = 600
override val name = "Pizza"
}
fun main() {
Pizza().consume() // "I'm eating Pizza"
}
31
When to use each
● Defining a broad spectrum of behavior or types? Consider an
interface.
● You can extend only one class, but implement one or more
interfaces. 32
Special classes
33
Data class
● Special class that exists just to store a set of data
35
Enum class
User-defined data type for a set of named values
36
Enum class example
Define an enum with red, green, and blue colors.
37
Object/singleton
38
Object/singleton example
object Calculator {
fun add(n1: Int, n2: Int): Int {
return n1 + n2
}
}
println(Calculator.add(2,4))
=> 6
39
Companion objects
● Lets all instances of a class share a single instance of a set of
variables or functions
40
Companion object example
class PhysicsSystem {
companion object WorldConstants {
val gravity = 9.8
val unit = "metric"
fun computeForce(mass: Double, accel: Double): Double {
return mass * accel
}
}
}
println(PhysicsSystem.WorldConstants.gravity)
println(PhysicsSystem.WorldConstants.computeForce(10.0, 10.0))
=> 9.8100.0
41
Organizing your code
42
Single file, multiple entities
● Kotlin DOES NOT enforce a single entity (class/interface)
per file convention
● You can and should group related structures in the same file
43
Packages
● Provide means for organization
package org.example.game
44
Example class hierarchy
org.example.vehicle
Vehicle
org.example.vehicle.moped org.example.vehicle.car
Moped Car
Moped50cc Sedan
Moped100cc Hatchback
45
Visibility modifiers
Use visibility modifiers to limit what information you expose.
46
Resources
● Classes and Inheritance
● Abstract classes
● Data Classes
● Companion Objects
● Visibility Modifiers
Extra topic: Extension functions
48
Extension functions
Add functions to an existing class that you cannot modify
directly.
● Appears as if the implementer added it
49
Why use extension functions?
● Add functionality to classes that are not open
● Separate out core API from helper methods for classes you
own
Define extension functions in an easily discoverable place such as in the same file
as the class, or a well-named function.
50
Extension function example
Add isOdd() to Int class:
3.isOdd()
51
Extra topic: Pair and Triple Classes
52
Pair and Triple
● Pair and Triple are predefined data classes that store
2 or 3 pieces of data respectively
53
Pair and Triple examples
val bookAuthor = Pair("Harry Potter", "J.K. Rowling")
println(bookAuthor)
=> (Harry Potter, J.K. Rowling)
54
Pair to
Pair's special to variant lets you omit parentheses and periods (infix
function).
It allows for more readable code
val bookAuth1 = "Harry Potter".to("J. K. Rowling")
val bookAuth2 = "Harry Potter" to "J. K. Rowling"
=> bookAuth1 and bookAuth2 are Pair (Harry Potter, J. K. Rowling)
55