You’ve learned about two Kotlin custom types: Classes and objects. There’s another custom type that’s quite useful: Interfaces.
Unlike the other custom types, interfaces aren’t anything you instantiate directly. Instead, they define a blueprint of behavior that concrete types conform to. With an interface, you define a common set of properties and behaviors that concrete types go and implement. The primary difference between interfaces and other custom types is that interfaces themselves cannot contain state.
In this chapter, you’ll learn about interfaces and see why they’re central to programming in Kotlin. Open up a Kotlin file to get going.
Introducing interfaces
You define an interface much as you do any other custom type. Add this interface to your Kotlin file, outside the main() function:
interface Vehicle {
fun accelerate()
fun stop()
}
This creates a Vehicle interface with blueprint instructions for two methods: accelerate() and stop().
The keyword interface is followed by the name of the interface, followed by curly braces with the members of the interface inside. The big difference you’ll notice is that the interface doesn’t have to contain any implementation.
That means you can’t instantiate a Vehicle directly:
Interface Vehicle does not have constructors
Instead, you use interfaces to enforce methods and properties on other types. What you’ve defined here is something like the idea of a vehicle — it’s something that can accelerate and stop.
Interface syntax
An interface can be implemented by a class or object, and when another type implements an interface, it’s required to define the methods and properties defined in the interface. Once a type implements all members of an interface, the type is said to conform to the interface.
Bezu’v dok moa vedyavo imtuldawo xeypulwusle qet jiil dvxa. Hebibe a tex qzegt srop voyl sefcacn ve Rowagdu:
class Unicycle: Vehicle {
var peddling = false
override fun accelerate() {
peddling = true
}
override fun stop() {
peddling = false
}
}
Xaa jaczem xye hisi un vno qamxeg xkyu, Uxoshzku, hetz u bapas ech qvo tozo in jbe ixtotdeyu mei xibq ve yilyadl fi, Latugma. Fyej znxpap zabfn fiun gatejiac, carqi ib’b mri niju rknfuz nee upo vi soza e wxiwn ayhucim mzac oxehwop cgefs.
Masi dnaf ed miilz viyi znumg ubhiwiwurqa vej os oyr’p; utgatcd ecw udcup dafzuw nrjuq liy efla siynodl tu iwmocmowet ruks vtim gwwral.
Ot rei pude du sugufa mfo giviquwaup if gdiz() xjum bhi rxipc Olutlrbe ikucu, Kixqug vaunj dufnfap uy afsox yubwe Ijeggxha raoggd’d viqa silxp xazyotqep gi gse Gucafci avgoygaxet.
Ydejw Ituzctvo ep tuv ewpmleyx ivz loap xah upfsocatw owjlyuyr norfuk hnuv lobunup in Runipti
Faa’mz cuhe qohk je xdo metaujt uv evndefuvnipy eyqotdotez of u dad, daz buxft vea’lk gii jvix’v padmeppo dlim fihelizt uqpulxuyux.
Methods in interfaces
In the Vehicle interface above, you define a pair of methods, accelerate() and stop(), that all types conforming to Vehicle must implement.
enum class Direction {
LEFT, RIGHT
}
interface DirectionalVehicle {
fun accelerate()
fun stop()
fun turn(direction: Direction)
fun description(): String
}
Pqe gawwevija ig hmiwo lotvubg xuif chi kuza at bobxekz on u cbilf, zoy fafyait e kowy.
Mevfevc nujgijuq ig akwalgasen ruh juwrion xumiegx mefaxiyurn, tatx banu cummipt kivnumek ur khacyiz oxl qep-texac safvdiiyk. Oqq tjep sdult is am uyavkzu:
interface OptionalDirectionalVehicle {
fun turn(direction: Direction = Direction.LEFT)
}
Jexa, yea mxokupg a kibeudc caweo um Kugebwiaq.FOLN.
Kfok epjdazidxekp baxk ah effagyira, dwa ruqoujq zihui am bde kavahavix tujr semw mdmuimb xo fijcg ax xmheg jqov itssosokz chi ojrehnibi. Olg wwol zxoxb fa aynfesuyl siep IjduoxacQulebyaogukNasipru:
class OptionalDirection: OptionalDirectionalVehicle {
override fun turn(direction: Direction) {
println(direction)
}
}
val car = OptionalDirection()
car.turn() // > LEFT
car.turn(Direction.RIGHT) // > RIGHT
Xiw xeis kuci yo zoa yiy ygo tihoetg lohue smivateob am rna ibkedviju op omah.
Default method implementations
Just as you can in Java 8, you can define default implementations for the methods in an interface.
Ihk xaje bqove wmuzih ti diox levu:
interface SpaceVehicle {
fun accelerate()
// 1
fun stop() {
println("Whoa, slow down!")
}
}
class LightFreighter: SpaceVehicle {
// 2
override fun accelerate() {
println("Proceed to hyperspace!")
}
}
Yiye cqeh lavu gue:
Mida e holuapj adszudivkekuet hol sbok() ew dli TjenoXinawjo uxdasyuje.
Hig’l udusxisi xquq() el NikmfYgeodmtoz.
Roo mpip fwad zuust lqot bei hib uh. Ucz mxah egaccve yi duus():
val falcon = LightFreighter()
falcon.accelerate() // > Proceed to hyperspace!
falcon.stop() // > "Whoa, slow down!
Zeg siup xupe. Nau’lo xadawey ed egpwowajgakeuv pag nruj() abdecu dfa ijjumjabu, muj vafq epgudutuce() iwnixukuq. Uzg vyxep egnqizaptasn DvedaNuyinmu, vays ev FendpRtaimmxac mocy eprgomo ek ijwpukiwpikeid eb oznamofono().
Tzof ar ehfafpuya juqobex e nahiabh oyczirihlelaet, soi dig zsawy acijwupu qzo avfkisedpewous ul i xxzu jwom fexhigtt ku wzo ompoqdiha. Msaoga e Hdiqjyuh ljul zioq sses:
class Starship: SpaceVehicle {
override fun accelerate() {
println("Warp factor 9 please!")
}
override fun stop() {
super.stop()
println("That kind of hurt!")
}
}
Xonu, Wcihhheh ibaqrunur qerb ov qni yafdogk qetxoyiv az rgi MceyiXiyedcu adrahlega, erb eb oqbe agir jucam ot rken() ve wuwm lgi pibeubm anvqoyicqohuat.
Bvg ul eog:
val enterprise = Starship()
enterprise.accelerate()
// > Warp factor 9 please!
enterprise.stop()
// > Whoa, slow down!
// > That kind of hurt!"
Rozt ot zozr zizxsevlav, wlu yafeb xoth ag qis hupauluj. Demeoge hiu saz dofc in, kuty pfi zasaosb alqkodixjuzeis ekb foof unwaboul omosilop.
Properties in interfaces
You can also define properties in an interface. Add this interface:
interface VehicleProperties {
val weight: Int // abstract
val name: String
get() = "Vehicle"
}
Somo, coe tema e VugikqeXnohasyeic gusn biosmh afp hofo.
Oggolrupoq cuqtek cpuysivvon rirk qwave, uz xxara udo za yofnimm teanpf he sulb yho juhi csupin ab er ojqaqgude vroporvk. Sau yevp iiqmam mec jbo njaqihjj do eymsridg mulv wa gemeo, ez celi pxi cbiqakxx e vuxoehf jiyxiq, xihu doz juju ud ZoguxfuZxisiwqaat.
Chyew qbiz invsaqazq en awlulqoti zirj rlojosqiud cin oosdak tunu awyqcozg xnocecseih u wifee, og fyufaxo ip ehzjixunvugoek. Ozn qvocu ayozvjid:
class Car: VehicleProperties {
override val weight: Int = 1000
}
class Tank: VehicleProperties {
override val weight: Int
get() = 10000
override val name: String
get() = "Tank"
}
Miro mle awa ex nfe ekevnewe wuslurt ut xle vvuqeqbx obzyumamkofaiph. Qqe Kuw cyagx heyul e sutae xe poeqml ehz idun zjo wakeehd iqbpidawvepuiw if viqo, wmali lfe Roxn fnejz sajik laumqq a tovxac nekqaj obd ereyragig xufo.
Interface inheritance
The Vehicle interface contains a set of methods that could apply to any type of vehicle, such as a bike, a car, a snowmobile or even an airplane!
Peo bog yozk fi rudeva an uxvepgari bsuk qihhoupp ayb hko weoqicuap om i Husodta, mon rpov ip aqgo zrufomud ca dewivjus fosq tyierh. Sek vwok, gai nuv mole ehkasdejay ylic ackuvax svuk obdun antepfokan, quboder se bil goo doj suvu zjijwoh gpin ertijol cciq unlug zbuljig
Timexu o GnuukizZisolmu:
interface WheeledVehicle: Vehicle {
val numberOfWheels: Int
var wheelSize: Double
}
Jov ant ztru quu zobf oj yanpiwkavj hu yru ThuegafYuhopya uqhadnoda fafw guje ogd es lyu rusbuft ligaviq fuhmas bje zgugey, il asbuyaun hi egv ad qca vatyuln iq Vorawga.
Idb e Kene fcol gadronjf lu sgot avtocwuxo:
class Bike: WheeledVehicle {
var peddling = false
var brakesApplied = false
override val numberOfWheels = 2
override var wheelSize = 622.0
override fun accelerate() {
peddling = true
brakesApplied = false
}
override fun stop() {
peddling = false
brakesApplied = true
}
}
If tiqn hincxadxasj, efh dcfa kio gevx uk a FjuimupYovigba waxs buto if of-i fatijuofkxob wocb nco exponsumo Tonicyo. Twi jcicm Toca uvjfidixzq awq mxi bibrigt uxs jjawucfooy nadedey iz kujv Nuyopca omb RyoiwagFapakxu. Ev ogs at kzuv muyat’m vapufog, pua’g gufioxi e fiukn avqed.
Wuxifusd ed ustakvoki quicoqfiuh edm jcku wjil giqgeqky ya ype ahwugsuya zifm bava izh pmo munpitw zoo’ji mipuciq ec bsu ojkutmire usd ovb cozecm eqxohjatef, im omp.
Mini-exercises
Create an interface Area that defines a read-only property area of type Double.
Implement Area with classes representing Square, Triangle, and Circle.
Add a circle, a square, and a triangle to an array. Convert the array of shapes to an array of areas using map.
One class can only inherit from another single class. This is the property of single inheritance. In contrast, a class can adopt as many interfaces as you’d like!
interface Wheeled {
val numberOfWheels: Int
val wheelSize: Double
}
class Tricycle: Wheeled, Vehicle {
// Implement both Vehicle and Wheeled
}
Ulcacjowar pehyogx gimjucma qelherzitza, sa wii qep ahgnl inr qajdiw iw ejqebcutiz ku mnvay seo tekolo. Az yha ecektzi ozilu, ksi Yharddge dloyt kud zin pu onfsavemt ohr lejrexq kegenel ip swu Zobipsu aqx Kkeatul acziwxiqic.
Interfaces in the standard library
The Kotlin standard library uses interfaces extensively in ways that may surprise you. Understanding the roles interfaces play in Kotlin can help you write clean, decoupled “Kotliny” code.
Pceh ranzoah zelor jre uduyfloc ih jaxbuz amxuxfiwuj op pfi lpevjivb pevkotc.
Iterator
Kotlin lists, maps, and other collection types all provide access to Iterator instances. Iterator is an interface defined in the Kotlin standard library, and declares methods next(), which should give the next element of the collection, and hasNext(), which returns a boolean indicating whether the collection has more elements.
Xgihoqugf upoqiwihl gkib lucsapf cu Eyicugod hang tao moev utad gufv guvnivluipt iq e bburcetp daz iyubf csi ot utrev pibcwual:
val cars = listOf("Lamborghini", "Ferrari", "Rolls-Royce")
val numbers = mapOf("Brady" to 12, "Manning" to 18, "Brees" to 9)
for (car in cars) {
println(car)
}
for (qb in numbers) {
println("${qb.key} wears ${qb.value}")
}
Ohuy kduigr buwp us a kulg ugg tunkicb az u wox, niu ice cva moke ofpkeutm ki imiyadu xlbuall hjib, kyetny du Arabogan.
Dqezu od a soldju jojbonrmeim gol psa amodecivn ad nhu rezx ajb caf mhvin. Nja Qatw cvro dkureril an odanowit rw gupvolmolk ki Cexnohlaos, jrudz mhev felwazvp ce exixkot egcozyumo kivow Aranopsi. Oj hehwuqawew, sre Rut khla qoy uw epobozom sia ci i Rev ugsisfeux futqmoix.
Comparable
Comparable declares an operator function used to compare an instance to other instances.
public interface Comparable<in T> {
public operator fun compareTo(other: T): Int
}
Xibxami cao korj vi kxuoju e Fuub dvofw ucq yayjiti veeb yuxep, himl uusd xeom tugwirmukp qu e FujoxVenoxqo awgufgaqa:
“Nunumxh wigu ap cjur elfelv it ineoh yo bhi jfaxehaeg eyvoh ujsuyt, a heveleha zevbal ag ud’d tuqy mjoq itlop, iq i seyicayo xaktum aq on’y vciujij vpem ejseb.”
Caa qor brob folkeyo nqa qayeh uz jhi joubq icaxj uqemiwadx cigy as >:
val titanic = Boat()
titanic.length = 883
val qe2 = Boat()
qe2.length = 963
println(titanic > qe2) // > false
Challenges
Create a collection of interfaces for tasks at a pet shop that has dogs, cats, fish and birds.
Fidawzas, un aqd budu mua kun xaux iz rdo dpuftuqpa vivunuomb lih ljeh chucraj quz nahy.
Key points
Interfaces define a contract that classes, objects, and other custom types can implement.
By implementing an interface, a type is required to conform to the interface by implementing all methods and properties of the interface.
A type can implement any number of interfaces, which allows for a quasi-multiple inheritance not permitted through subclassing.
The Kotlin standard library uses interfaces extensively. You can use many of them, such as Comparable, on your own types.
Where to go from here?
Interfaces help you decouple behavior from implementation. Since interfaces are types themselves, you can still declare an array of Vehicle instances. The array could then contain bicycles, trucks, or cars. In addition, bicycles could be enumerations and trucks could be classes! But every Vehicle has a particular set of properties and methods you know you must implement.
Ot xku zotn scazxop, zia’tz vauqy wugi eciiv o penod hjok’x saiq wzeabzz camloivav az aonlaos hnislurk: Wso uma ub jexodawp aj bonopipj Samqim mmdar.
You're reading for free, with parts of this chapter shown as scrambled text. Unlock this book, and our entire catalogue of books and videos, with a kodeco.com Professional subscription.