0% found this document useful (0 votes)
7 views55 pages

3-Classes and Objects

This lesson covers the fundamentals of classes and objects in Kotlin, including class definitions, constructors, inheritance, and special classes like data and enum classes. It also discusses organizing code with packages and visibility modifiers, as well as extension functions that add functionality to existing classes. Key concepts such as primary constructors, custom getters/setters, and the use of companion objects are also highlighted.
Copyright
© © All Rights Reserved
We take content rights seriously. If you suspect this is your content, claim it here.
Available Formats
Download as PDF, TXT or read online on Scribd
0% found this document useful (0 votes)
7 views55 pages

3-Classes and Objects

This lesson covers the fundamentals of classes and objects in Kotlin, including class definitions, constructors, inheritance, and special classes like data and enum classes. It also discusses organizing code with packages and visibility modifiers, as well as extension functions that add functionality to existing classes. Key concepts such as primary constructors, custom getters/setters, and the use of companion objects are also highlighted.
Copyright
© © All Rights Reserved
We take content rights seriously. If you suspect this is your content, claim it here.
Available Formats
Download as PDF, TXT or read online on Scribd
You are on page 1/ 55

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

class House { val myHouse = House()


val color: String = "white" println(myHouse)
val numberOfWindows: Int = 2
val isForSale: Boolean = false

fun updateColor(newColor: String){...}


...
}

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()

class B(x: Int) val bb = B(12)


println(bb.x)
=> compiler error unresolved
reference

class C(val y: Int) val cc = C(42)


println(cc.y)
=> 42

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:

class Square(val side: Int) {


init {
println(side * 2)
}
}

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

● Secondary constructor body is not required

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:

● Override get() for a property


● Override set() for a property (if defined as a var)

Format: var propertyName: DataType = initialValue


get() = ...
set(value) {
...
}

17
Custom getter
class Person(val firstName: String, val lastName:String) {
val fullName:String
get() {
return "$firstName $lastName"
}
}

val person = Person("John", "Doe")


println(person.fullName)
=> John Doe

18
Custom setter
var fullName:String = ""
get() = "$firstName $lastName"
set(value) {
val components = value.split(" ")
firstName = components[0]
lastName = components[1]
field = value
}

person.fullName = "Jane Smith"

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

● Can contain method signatures and property names

● Can derive from other interfaces

Format: interface NameOfInterface { interfaceBody }

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

● Kotlin classes by default are not subclassable

● Use open keyword to allow subclassing

● Properties and functions are redefined with the override


keyword

26
Classes are final by default
Declare a class
class A

Try to subclass A
class B : A

=>Error: A is final and cannot be inherited from

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)

● Must use override when overriding properties and methods

● Something marked override can be overridden in subclasses


(unless marked final)

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.

● Will the behavior be specific to that type? Consider a class.

● Need to inherit from multiple classes? Consider refactoring code to


see if some behavior can be isolated into an interface.

● Want to leave some properties / methods abstract to be defined by


subclasses? Consider an abstract class.

● 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

● Mark the class with the data keyword

● Generates getters for each property (and setters for vars


too)

● Generates toString(), equals(), hashCode(), copy()


methods, and destructuring operators

Format: data class <NameOfClass>( parameterList )


34
Data class example
Define the data class:
data class Player(val name: String, val score: Int)

Use the data class:


val firstPlayer = Player("Lauren", 10)
println(firstPlayer)
=> Player(name=Lauren, score=10)

Data classes make your code much more concise!

35
Enum class
User-defined data type for a set of named values

● Use this to require instances be one of several constant values


● The constant value is, by default, not visible to you
● Use enum before the class keyword

Format: enum class EnumName { NAME1, NAME2, … NAMEn }


Referenced via EnumName.<ConstantName>

36
Enum class example
Define an enum with red, green, and blue colors.

enum class Color(val r: Int, val g: Int, val b: Int) {


RED(255, 0, 0), GREEN(0, 255, 0), BLUE(0, 0, 255)
}

println("" + Color.RED.r + " " + Color.RED.g + " " + Color.RED.b)


=> 255 0 0

37
Object/singleton

● Sometimes you only want one instance of a class to ever


exist

● Use the object keyword instead of the class keyword

● Accessed with NameOfObject.<function or variable>

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

● Use companion keyword

● Referenced via ClassName.PropertyOrFunction

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

● Be mindful of file length and clutter

43
Packages
● Provide means for organization

● Identifiers are generally lower case words separated by


periods

● Declared in the first non-comment line of code in a file


following the package keyword

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.

● public means visible outside the class. Everything is public by default,


including variables and methods of the class.
● private means it will only be visible in that class (or source file if you are
working with functions).
● protected is the same as private, but it will also be visible to any
subclasses.

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

● Not actually modifying the existing class

● Cannot access private instance variables

Format: fun ClassName.functionName( params ) { body }

49
Why use extension functions?
● Add functionality to classes that are not open

● Add functionality to classes you don’t own

● 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:

fun Int.isOdd(): Boolean { return this % 2 == 1 }

Call isOdd() on an Int:

3.isOdd()

Extension functions are very powerful in Kotlin!

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

● Access variables with .first, .second, .third


respectively

● Usually named data classes are a better option


(more meaningful names for your use case)

53
Pair and Triple examples
val bookAuthor = Pair("Harry Potter", "J.K. Rowling")
println(bookAuthor)
=> (Harry Potter, J.K. Rowling)

val bookAuthorYear = Triple("Harry Potter", "J.K. Rowling", 1997)


println(bookAuthorYear)
println(bookAuthorYear.third)
=> (Harry Potter, J.K. Rowling, 1997)
1997

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)

Also used in collections like Map and HashMap


val map = mapOf(1 to "x", 2 to "y", 3 to "zz")
=> map of Int to String {1=x, 2=y, 3=zz}

55

You might also like