Kotlin is een moderne programmeertaal die compileert met Java bytecode. Het is gratis en open source en belooft om het coderen voor Android nog leuker te maken.
In het vorige artikel hebt u meer informatie gekregen over Kotlin-eigenschappen zoals late-initialisatie, extensie en inline-eigenschappen. Niet alleen dat, je hebt ook geleerd over geavanceerde klassen zoals data, enum, geneste en verzegelde klassen in Kotlin.
In dit bericht blijf je leren over objectgeoriënteerd programmeren in Kotlin door te leren over abstracte klassen, interfaces en overerving. Voor een bonus leer je ook over type aliassen.
Kotlin ondersteunt abstracte klassen - net als Java zijn dit klassen waarvan je nooit van plan bent objecten te maken. Een abstracte klasse is onvolledig of nutteloos zonder een aantal concrete (niet-abstracte) subklassen, waaruit u objecten kunt instantiëren. Een concrete subklasse van een abstracte klasse implementeert alle methoden en eigenschappen gedefinieerd in de abstracte klasse, anders is die subklasse ook een abstracte klasse!
We creëren een abstracte klasse met de abstract
modifier (vergelijkbaar met Java).
abstracte klasse Werknemer (val firstName: String, val lastName: String) abstract fun earnings (): Double
Merk op dat niet alle leden abstract moeten zijn. Met andere woorden, we kunnen methode-standaardimplementatie in een abstracte klasse hebben.
abstracte klasse Werknemer (val firstName: String, val lastName: String) // ... fun fullName (): String return lastName + "" + firstName;
Hier hebben we de niet-abstracte functie gemaakt voor-en achternaam()
in een abstracte klasse werknemer
. Betonklassen (subklassen van de abstracte klasse) kunnen de standaardimplementatie van een abstracte methode overschrijven, maar alleen als de methode de Open
modifier opgegeven (hier komt u binnenkort meer over te weten).
We kunnen ook staat opslaan in abstracte klassen.
abstracte klasse Werknemer (val firstName: String, val lastName: String) // ... val propFoo: String = "bla bla"
Zelfs als de abstracte klasse geen methoden definieert, moeten we een subklasse maken voordat we deze kunnen instantiëren, zoals in het onderstaande voorbeeld.
class Programmer (firstName: String, lastName: String): Employee (firstName, lastName) overschrijft leuke inkomsten (): verdubbelen // inkomsten berekenen
Onze Programmeur
class breidt het uit werknemer
abstracte klasse. In Kotlin gebruiken we een enkel dubbel teken (:
) in plaats van Java strekt
sleutelwoord om een klasse uit te breiden of een interface te implementeren.
We kunnen vervolgens een object van het type maken Programmeur
en bel methoden erop - hetzij in zijn eigen klasse of de superklasse (basisklasse).
val programmeur = Programmeur ("Chike", "Mgbemena") println (programmer.fullName ()) // "Mgbemena Chike"
Een ding dat je zou kunnen verbazen is dat we de mogelijkheid hebben om een te vervangen val
(onveranderlijk) eigendom met var
(veranderlijk).
open class BaseA (open val baseProp: String) class DerivedA: BaseA ("") private var derivedProp: String = "" negeer var baseProp: String get () = derivedProp set (waarde) derivedProp = value
Zorg ervoor dat u deze functionaliteit verstandig gebruikt! Houd er rekening mee dat we de omgekeerde a niet kunnen doen var
woning met val
.
Een interface is eenvoudigweg een verzameling gerelateerde methoden waarmee u standaard objecten kunt vertellen wat u moet doen en ook hoe u dit standaard moet doen. (Standaardmethoden in interfaces zijn een nieuwe functie toegevoegd aan Java 8.) Met andere woorden, een interface is een contract dat door klassen wordt geïmplementeerd..
Een interface wordt gedefinieerd met behulp van de interface
trefwoord in Kotlin (vergelijkbaar met Java).
class Result class Student interface StudentRepository fun getById (id: Long): Student fun getResultsById (id: Long): Lijst
In de bovenstaande code hebben we een verklaard StudentRepository
interface. Deze interface bevat twee abstracte methoden: getById ()
en getResultsById ()
. Merk op dat de abstract
trefwoord is overbodig in een interfacemethode omdat ze al impliciet abstract zijn.
Een interface is nutteloos zonder een of meer implementeerders, dus laten we een klasse maken die deze interface implementeert.
class StudentLocalDataSource: StudentRepository overschrijven leuk getResults (id: lang): lijst// do implementation overschrijven leuk getById (id: lang): student // do implementation
Hier hebben we een klas gemaakt StudentLocalDataSource
dat implementeert de StudentRepository
interface.
Wij gebruiken de override
modifier om de methoden en eigenschappen te labelen die we opnieuw willen definiëren vanuit de interface of superklasse, dit is vergelijkbaar met de @ Override
annotatie in Java.
Let op de volgende aanvullende regels van interfaces in Kotlin:
override
modifier is verplicht in Kotlin-in tegenstelling tot Java. Laten we een voorbeeld van een interfacemethode bekijken met een standaardimplementatie.
interface StudentRepository // ... fun delete (student: student) // do implementatie
In de voorgaande code hebben we een nieuwe methode toegevoegd wissen ()
met een standaardimplementatie (hoewel ik de daadwerkelijke implementatiecode niet heb toegevoegd voor demonstratiedoeleinden).
We hebben ook de vrijheid om de standaardimplementatie te overschrijven als we dat willen.
klas StudentLocalDataSource: StudentRepository // ... overschrijven leuke verwijdering (student: student) // do implementatie
Zoals gezegd, kan een Kotlin-interface eigenschappen hebben, maar merk op dat deze de status niet kan behouden. (Onthoud echter dat abstracte klassen de status kunnen behouden.) Dus de volgende interfacedefinitie met een eigenschapverklaring werkt.
interface StudentRepository val propFoo: Boolean // zal werken // ...
Maar als we proberen een of andere status toe te voegen aan de interface door een waarde toe te kennen aan de eigenschap, zal deze niet werken.
interface StudentRepository val propFoo: Boolean = true // Fout: eigenschap-initializers zijn niet toegestaan in interfaces // ...
Een interface-eigenschap in Kotlin kan echter getter- en settermethoden hebben (hoewel alleen de laatste als de eigenschap veranderbaar is). Merk ook op dat de eigenschap in een interface geen back-veld kan hebben.
interface StudentRepository var propFoo: Boolean get () = true set (value) if (value) // do something // ...
We kunnen ook een interface-eigenschap desgewenst overschrijven om deze opnieuw te definiëren.
class StudentLocalDataSource: StudentRepository // ... negeer var propFoo: Boolean get () = false set (value) if (value)
Laten we eens kijken naar een geval waarin we een klasse hebben die meerdere interfaces implementeert met dezelfde methodesignatuur. Hoe beslist de klas welke interfacemethode te bellen?
interface InterfaceA fun funD () interface InterfaceB fun funD ()
Hier hebben we twee interfaces met een methode met dezelfde handtekening fonds()
. Laten we een klasse maken die deze twee interfaces implementeert en de. Overschrijft fonds()
methode.
class classA: InterfaceA, InterfaceB override fun funD () super.funD () // Fout: er zijn veel supertypes beschikbaar, geef dan aan welke u bedoelt onder punthaken, bijv. 'super'
De compiler is verward over het bellen van de super.funD ()
methode omdat de twee interfaces die de klasse implementeert dezelfde methodesignatuur hebben.
Om dit probleem op te lossen, verpakken we de interfacenaam waarvoor we de methode tussen punthaken willen noemen
. (IntelliJ IDEA of Android Studio geeft u een hint over het oplossen van dit probleem wanneer het opduikt.)
class classA: InterfaceA, InterfaceB override fun funD () super.funD ()
Hier gaan we de fonds()
methode van InterfaceA
. Probleem opgelost!
Een nieuwe klasse (subklasse) wordt gemaakt door een bestaande klasse (superklasse) leden te verwerven en misschien hun standaardimplementatie opnieuw te definiëren. Dit mechanisme staat bekend als erfenis in object-georiënteerd programmeren (OOP). Een van de dingen die Kotlin zo geweldig maken, is dat het zowel de OOP- als de functionele programmeerparadigma omvat - alles in één taal.
De basisklasse voor alle klassen in Kotlin is Ieder
.
class Person: Any
De Ieder
type is gelijk aan de Voorwerp
type dat we in Java hebben.
openbare open klasse Any public open operator fun equals (other: Any?): Boolean public open fun hashCode (): Int public open fun toString (): String
De Ieder
type bevat de volgende leden: is gelijk aan ()
, Hashcode ()
, en ook toString ()
methoden (vergelijkbaar met Java).
Onze klassen hoeven dit type niet expliciet uit te breiden. Als u niet expliciet opgeeft in welke klasse een nieuwe klasse zich uitbreidt, wordt de klasse uitgebreid Ieder
impliciet. Om deze reden hoeft u dit meestal niet op te nemen : Ieder
in uw code - we doen dit in de bovenstaande code voor demonstratiedoeleinden.
Laten we nu kijken naar het creëren van lessen in Kotlin met het oog op erfgoed.
klas Student klas GraduateStudent: Student ()
In de bovenstaande code, de GraduateStudent
class breidt de superklasse uit Student
. Maar deze code compileert niet. Waarom? Omdat klassen en methoden zijn laatste
standaard in Kotlin. Met andere woorden, ze kunnen niet standaard worden uitgebreid, in tegenstelling tot Java, waar klassen en methoden standaard zijn geopend.
Aanbevolen procedures voor softwaretechnologie bevelen aan dat u begint met het maken van uw klassen en methoden laatste
standaard - d.w.z. als ze niet specifiek zijn bedoeld om opnieuw te worden gedefinieerd of te worden onderdrukt in subklassen. Het Kotlin-team (JetBrains) paste deze codeerfilosofie en nog veel meer praktische ontwikkelingspraktijken toe bij het ontwikkelen van deze moderne taal.
Om subklassen van een superklasse te kunnen maken, moeten we de superklasse expliciet markeren met de Open
modifier. Deze wijziging is ook van toepassing op elke superklasse-eigenschap of -methode die moet worden overschreven door subklassen.
open klasse Student
We plaatsen gewoon de Open
modifier voor de klasse
trefwoord. We hebben nu de compiler opdracht gegeven om onze Student
klasse om open te staan voor extensie.
Zoals eerder vermeld, zijn leden van een Kotlin-klasse standaard ook definitief.
open klasse Student open leuk schoolgeld (): BigDecimal // do implementatie
In de voorgaande code hebben we de schoolgeld
Functioneert als Open
-zodat subklassen het kunnen negeren.
open class GraduateStudent: Student () override fun schoolFees (): BigDecimal return super.schoolFees () + calculationSchoolFees () private fun calculateSchoolFees (): BigDecimal // schoolkosten berekenen en inleveren
Hier, de open schoolgeld
functie van de superklasse Student
wordt overschreven door de GraduateStudent
klasse - door de override
modifier voor de pret
trefwoord. Merk op dat als u een lid van een superklasse of interface opheft, het overheersende lid dat ook is Open
standaard, zoals in het onderstaande voorbeeld:
class ComputerScienceStudent: GraduateStudent () override fun schoolFees (): BigDecimal retourneer super.schoolFees () + calculationSchoolFess () private fun calculateSchoolFess (): BigDecimal // bereken en retourneer schoolgeld
Hoewel we het niet hebben gemarkeerd Schoolgeld ()
methode in de GraduateStudent
klasse met de Open
modifier, we kunnen het nog steeds negeren, zoals we deden in de ComputerScienceStudent
klasse. Om dit te voorkomen, moeten we het overheersende lid markeren als laatste
.
Vergeet niet dat we nieuwe functionaliteit aan een klasse kunnen toevoegen, zelfs als die definitief is, door het gebruik van uitbreidingsfuncties in Kotlin. Voor een opfriscursus over uitbreidingsfuncties, bekijk mijn geavanceerde functies in Kotlin-bericht. Als je een opfriscursus nodig hebt over hoe je zelfs een laatste klas nieuwe eigenschappen kunt geven zonder ervan te erven, lees dan het gedeelte over de extensie Eigenschappen in mijn Geavanceerde eigenschappen en klassen.
Als onze superklasse een primaire constructor als deze heeft:
open klasse Student (val firstName: String, val lastName: String) // ...
Vervolgens moet elke subklasse de primaire constructor van de superklasse aanroepen.
open class GraduateStudent (firstName: String, lastName: String): Student (firstName, lastName) // ...
We kunnen eenvoudig een object van de maken GraduateStudent
klasse zoals gebruikelijk:
val graduateStudent = GraduateStudent ("Jon", "Snow") println (graduateStudent.firstName) // Jon
Als de subklasse de superclass-constructor van de secundaire constructor wil aanroepen, gebruiken we de super
keyword (vergelijkbaar met hoe superclass constructors worden aangeroepen in Java).
open class GraduateStudent: Student // ... private var thesis: String = "" constructor (firstName: String, lastName: String, thesis: String): super (firstName, lastName) this.thesis = thesis
Als je opfriscursussen nodig hebt bij klasconstructeurs in Kotlin, bezoek dan alstublieft mijn Classes and Objects-post.
Een ander geweldig ding dat we kunnen doen in Kotlin is om een type een alias te geven.
Laten we een voorbeeld bekijken.
data class Person (val firstName: String, val lastName: String, val age: Int)
In de bovenstaande klas kunnen we de Draad
en Int
typen voor de Persoon
eigenschappen aliassen met behulp van de typealias
modifier in Kotlin. Deze modifier wordt gebruikt om een alias van elk type in Kotlin te maken, inclusief degenen die je hebt gemaakt.
typealias Name = String typealias Age = Int data class Person (val firstName: Name, val lastName: Name, val age: Age)
Zoals u kunt zien, hebben we een alias gemaakt Naam
en Leeftijd
voor zowel de Draad
en Int
typen respectievelijk. We hebben nu de Voornaam
en achternaam
eigenschaptype voor onze alias Naam
-en ook Int
type naar Leeftijd
alias. Merk op dat we geen nieuwe typen hebben gemaakt - in plaats daarvan hebben we een alias voor de typen gemaakt.
Deze kunnen handig zijn als u een betere betekenis of semantiek wilt geven aan typen in uw Kotlin-codebase. Gebruik ze dus verstandig!
In deze tutorial leer je meer over objectgeoriënteerd programmeren in Kotlin. We hebben het volgende behandeld:
Als je Kotlin hebt leren kennen via onze Kotlin From Scratch-serie, zorg er dan voor dat je de code die je ziet hebt ingevoerd en deze op je IDE hebt uitgevoerd. Een goede tip om echt een nieuwe programmeertaal (of een ander programmeerconcept) te begrijpen, is om ervoor te zorgen dat u niet alleen de leermiddelen of handleiding leest, maar ook de eigenlijke code typt en uitvoert!
In de volgende zelfstudie in de Kotlin From Scratch-serie maakt u kennis met de afhandeling van uitzonderingen in Kotlin. Tot ziens!
Voor meer informatie over de Kotlin-taal, raad ik aan de Kotlin-documentatie te bezoeken. Of bekijk enkele van onze andere Android-apps voor app-ontwikkeling hier op Envato Tuts!