Kotlin de la zero clase abstracte, interfețe, moștenire și alias de tip

Kotlin este un limbaj de programare modern care se compilează la Java bytecode. Este gratuit și open source, și promite să facă codificarea pentru Android chiar mai distractiv.  

În articolul precedent, ați aflat mai multe despre proprietățile Kotlin, cum ar fi proprietăți de întârziere, extensie și inline. Nu numai că ați învățat despre cursuri avansate, cum ar fi date, enum, imbricate și clase sigilate în Kotlin. 

În acest post, veți continua să învățați despre programarea orientată pe obiecte în Kotlin, învățând despre clase abstracte, interfețe și moștenire. Pentru un bonus, veți afla, de asemenea, despre aliasurile de tip. 

1. Clasele Abstract

Kotlin susține clasele abstracte - la fel ca Java, acestea sunt clase pe care niciodată nu intenționați să le creați. O clasă abstractă este incompletă sau inutilă fără niște subclase concrete (ne-abstracte), de la care puteți instanțiza obiecte. O subclasă concretă a unei clase abstracte implementează toate metodele și proprietățile definite în clasa abstractă - altfel subclasa este, de asemenea, o clasă abstractă!

Creați o clasă abstractă cu abstract modificator (similar cu Java). 

clasa abstractă Angajat (val firstName: String, val lastName: String) câștig distractiv abstract (): Double

Rețineți că nu toți membrii trebuie să fie abstracți. Cu alte cuvinte, putem avea implementarea implicită a metodei într-o clasă abstractă. 

clasa abstractă Angajat (val firstName: String, val lastName: String) // ... distracție fullName (): String return lastName + "" + firstName; 

Aici am creat funcția non-abstractă Numele complet() într-o clasă abstractă Angajat. Clasele concrete (subclasele din clasa abstractă) pot înlocui implementarea implicită a metodei abstracte - dar numai dacă metoda are deschis modificator specificat (veți afla mai multe despre acest lucru în scurt timp). 

De asemenea, putem stoca statul în clase abstracte. 

clasa abstractă Angajat (val firstName: String, val lastName: String) // ... val propFoo: String = "bla bla"

Chiar dacă clasa abstractă nu definește nici o metodă, trebuie să creăm o subclasă înainte de a o instanțiate, ca în exemplul de mai jos.

programator de clasă (firstName: String, lastName: String): Angajat (firstName, lastName) câștiguri de distracție (): dublu // calculați câștigurile

Al nostru Programator clasa extinde Angajat clasă abstractă. În Kotlin folosim un singur caracter de colon (:) în loc de Java extinde cuvinte cheie pentru a extinde o clasă sau a implementa o interfață. 

Putem apoi crea un obiect de tip Programator și metodele de apel pe ea - fie în propria sa clasă, fie în superclasa (clasa de bază).  

val programmer = programator ("Chike", "Mgbemena") println (programmer.fullName ()) // "Mgbemena Chike"

Un lucru care te-ar putea surprinde este că avem abilitatea de a suprascrie Val (imuabil) cu var (mutabil). 

open class BaseA (open val baseProp: String)  clasa DerivedA: BaseA ("") private var derivatProp: String = "" suprascrie var baseProp: String get () = derivatProp set (valoare) derivedProp = value

Asigurați-vă că utilizați această funcție cu înțelepciune! Fiți conștienți de faptul că nu putem face schimbarea inversă a var proprietate cu Val

2. Interfețe

O interfață este pur și simplu o colecție de metode asociate care de obicei vă permit să spuneți obiectelor ce trebuie să faceți și, de asemenea, cum să le faceți în mod implicit. (Metodele implicite în interfețe sunt o nouă caracteristică adăugată la Java 8.) Cu alte cuvinte, o interfață este un contract pe care clasele de implementare trebuie să le respecte. 

O interfață este definită folosind interfață cuvânt cheie în Kotlin (similar cu Java). 

clasa de rezultate Clasa de rezultate StudentRepository fun getById (id: Long): Student distracție getResultsById (id: Long): Listă 

În codul de mai sus, am declarat a StudentRepository interfață. Această interfață conține două metode abstracte: getById () și getResultsById (). Rețineți că inclusiv abstract cuvântul cheie este redundant într-o metodă de interfață, deoarece este deja implicit abstract. 

O interfață este inutilă fără unul sau mai mulți implementatori - așa că să creăm o clasă care va implementa această interfață. 

class StudentLocalDataSource: StudentRepository suprascrie distracție getResults (id: Long): Listă // punerea în aplicare suprascrie distracție getById (id: Long): Student // face implementare

Aici am creat o clasă StudentLocalDataSource care implementează StudentRepository interfață.

Noi folosim trece peste modificator pentru a eticheta metodele și proprietățile pe care vrem să le redefinem din interfață sau superclasă - aceasta este similară cu @Trece peste adnotare în Java.

Rețineți următoarele reguli suplimentare de interfețe în Kotlin:

  • O clasă poate implementa cât mai multe interfețe pe care le doriți, dar poate extinde numai o singură clasă (similară cu Java).
  •  trece peste modificatorul este obligatoriu în Kotlin - spre deosebire de Java. 
  • Împreună cu metodele, putem declara și proprietăți într-o interfață Kotlin. 
  • O metodă de interfață Kotlin poate avea o implementare implicită (similară cu Java 8). 

Să vedem un exemplu de metodă de interfață cu o implementare implicită.

interfață StudentRepository // ... fun delete (student: student) // face implementare

În codul precedent, am adăugat o nouă metodă șterge() cu o implementare implicită (deși nu am adăugat codul de implementare real pentru demonstrații). 

De asemenea, avem libertatea de a suprascrie implementarea implicită dacă vrem.

class StudentLocalDataSource: StudentRepository // ... suprascrie distracție ștergere (student: Student) // face implementare

După cum sa menționat, o interfață Kotlin poate avea proprietăți - dar rețineți că nu poate menține statul. (Cu toate acestea, amintiți clasele abstracte pot menține statul.) Deci, următoarea definiție a interfeței cu o declarație de proprietate va funcționa.

interfață StudentRepository val propFoo: Boolean // va funcționa // ...

Dar dacă încercăm să adăugăm o anumită stare la interfață atribuind o valoare proprietății, nu va funcționa.

interfață StudentRepository val propFoo: Boolean = true // Eroare: inițializatorii proprietăților nu sunt permise în interfețe // ...

Cu toate acestea, o proprietate de interfață în Kotlin poate avea metode getter și setter (deși numai ultima dacă proprietatea este mutable). Rețineți, de asemenea, că proprietatea într-o interfață nu poate avea un câmp de asistență. 

interfață StudentRepository var propFoo: Boolean get () = adevărat set (valoare) if (valoare) // face ceva // ...

De asemenea, putem suprascrie o proprietate a interfeței dacă doriți, pentru ao redefini. 

class StudentLocalDataSource: StudentRepository // ... suprascrie var propFoo: Boolean get () = set false (valoare) if (value) 

Să examinăm un caz în care avem o clasă care implementează mai multe interfețe cu aceeași semnătură de metodă. Cum determină clasa ce metodă de interfață trebuie apelată?

interfața InterfaceA fun funD ()  interfață InterfaceB fun funD () 

Aici avem două interfețe care au o metodă cu aceeași semnătură fond(). Să creăm o clasă care implementează aceste două interfețe și suprascrie fond() metodă. 

Clasa classA: InterfaceA, InterfaceB override fun funD () super.funD () // Eroare: Multe supertipuri disponibile, vă rugăm să precizați una dintre ele în paranteze unghiulare, de ex. 'super'

Compilatorul este confuz cu privire la apelarea super.funD () pentru că cele două interfețe pe care le implementează clasa au aceeași semnătură de metodă. 

Pentru a rezolva această problemă, vom împacheta numele interfeței pentru care dorim să numim metoda în paranteze unghiulare . (IntelliJ IDEA sau Android Studio vă va oferi un indiciu despre rezolvarea acestei probleme când se cultivă.)

clasa classA: InterfaceA, InterfaceB override fun funD () super.funD ()

Aici o vom numi fond()  Metodă de InterfaceA. Problema rezolvata! 

3. Moștenire

O nouă clasă (subclasa) este creată prin achiziționarea unui membru al clasei existente (superclass) și, probabil, redefinirea implementării implicite. Acest mecanism este cunoscut sub numele de moştenire în programarea orientată pe obiecte (OOP). Unul dintre lucrurile care îl fac pe Kotlin atât de minunat este că acesta cuprinde atât OOP, cât și paradigme de programare funcțională - toate într-o singură limbă.

Clasa de bază pentru toate clasele din Kotlin este Orice

persoană clasă: orice 

Orice tip este echivalent cu Obiect tipul pe care îl avem în Java. 

public open class Orice public open operator distractiv egal (alt: Any?): Boolean public open distracție hashCode (): Int public deschis distracție toString (): String

Orice tip conține următorii membri: este egal cu (), hashCode (), Si deasemenea toString () metode (similare cu Java). 

Clasele noastre nu trebuie să extindă în mod explicit acest tip. Dacă nu specificați în mod explicit ce clasă se extinde, clasa se extinde Orice implicit. Din acest motiv, de obicei nu trebuie să includeți : Orice în codul dvs. - facem acest lucru în codul de mai sus pentru demonstrații. 

 Să ne gândim acum la crearea de clase în Kotlin cu moștenire în minte. 

clasa Student  clasa Student absolvent: Student () 

În codul de mai sus, Absolvent clasa extinde superclama Student. Dar acest cod nu se va compila. De ce? Deoarece sunt clase și metode final implicit în Kotlin. Cu alte cuvinte, ele nu pot fi prelungite în mod prestabilit - spre deosebire de Java unde clasele și metodele sunt deschise implicit. 

Cele mai bune practici de inginerie software vă recomandă să începeți să faceți clasele și metodele final în mod prestabilit, adică dacă nu sunt destinate în mod specific să fie redefinite sau înlocuite în subclase. Echipa Kotlin (JetBrains) a aplicat această filozofie de codificare și multe alte bune practici de dezvoltare în dezvoltarea acestui limbaj modern. 

Pentru a permite ca subclasele să fie create dintr-o superclasă, trebuie să marcați în mod explicit superclaza cu deschis modificator. Acest modificator se aplică și în cazul oricăror proprietăți sau metode superclass care ar trebui să fie suprascrise de subclase.

curs deschis student 

Am pus pur și simplu deschis modificator înainte de clasă cuvinte cheie. Am instruit acum compilatorul să ne permită Student clasa să fie deschisă pentru extindere. 

După cum sa afirmat mai devreme, membrii unei clase Kotlin sunt, de asemenea, definitivi în mod implicit. 

clase deschise Student open fun schoolFees (): BigDecimal // face implementare

În codul precedent, am marcat Taxe școlare funcție ca deschis-astfel încât subclasele să o înlocuiască. 

open class Student () override distracție schoolFees (): BigDecimal return super.schoolFees () + calculateSchoolFees () distracție privată calculateSchoolFees (): BigDecimal // calcula și returnează taxele de școală

Aici, deschis Taxe școlare funcția de la superclaj Student este suprascris de Absolvent clasă - prin adăugarea trece peste modificator înainte de distracţie cuvinte cheie. Rețineți că dacă înlocuiți un membru al unei superclase sau al unei interfețe, membrul suprem va fi de asemenea deschis în mod implicit, ca în exemplul de mai jos:

clasa ComputerScienceStudent: GraduateStudent () override distracție schoolFees (): BigDecimal return super.schoolFees () + calculateSchoolFess () distracție privată calculateSchoolFess (): BigDecimal // calcula și returnează taxele de școală

Chiar dacă nu l-am marcat Taxe școlare() metodă în Absolvent clasa cu deschis modificator, îl putem suprascrie - așa cum am făcut în ComputerScienceStudent clasă. Pentru a preveni acest lucru, trebuie să marcăm membrul suprem final

Amintiți-vă că putem adăuga noi funcționalități unei clase - chiar dacă este finală - prin utilizarea funcțiilor de extensie în Kotlin. Pentru o reîmprospătare a funcțiilor de extensie, verificați funcțiile avansate ale postului meu de la Kotlin. De asemenea, dacă aveți nevoie de o reîmprospătare a modului de a da chiar și unei proprietăți noi clasa finală fără a moșteni de la ea, citiți secțiunea privind extensia Proprietăți în postul meu de proprietăți avansate și clase. 

Dacă superclajul nostru are un constructor primar în felul următor:

clasa open class Student (val primul nume: String, val lastName: String) // ...

Apoi orice subclasă trebuie să apeleze constructorul primar al superclasei. 

clasă deschisă AbsolventăStudent (numeName: String, NumeNumăuie: String): Student (FirstName, lastName) // ...

Putem crea pur și simplu un obiect al Absolvent clasă ca de obicei:

val absolventStudent = student absolvent ("Jon", "zăpadă") println (absolventStudent.firstName) // Jon

Dacă subclasa dorește să apeleze constructorul superclass de la constructorul său secundar, vom folosi super cuvânt cheie (similar cu modul în care constructorii superclass sunt invocați în Java). 

open class Student: Student // ... teză privată var: String = "" constructor (numeName: String, lastName: String, teză: String): super (FirstName, lastName) this.thesis = teza

Dacă aveți nevoie de un curs de perfecționare pentru constructorii de clasă din Kotlin, vizitați-mi postul de Clase și Obiecte. 

4. Bonus: Alias ​​de tip

Un alt lucru minunat pe care îl putem face în Kotlin este să dăm un tip un pseudonim. 

Să vedem un exemplu.

clasa de date Persoana (val name: String, val lastName: String, val age: Int)

În clasa de mai sus, putem aloca Şir și Int tipuri pentru Persoană aliasuri de proprietăți utilizând typealias modificator în Kotlin. Acest modificator este folosit pentru a crea un alias de orice tip în Kotlin - inclusiv cele pe care le-ați creat. 

typealias Nume = String typealias Vârsta = Int clasa de date Persoană (val firstName: Nume, val lastName: Nume, val: Age) 

După cum puteți vedea, am creat un pseudonim Nume și Vârstă pentru ambele Şir și Int tipuri. Am înlocuit acum Nume și numele de familie tipul de proprietate în aliasul nostru Nume-Si deasemenea Int tip la Vârstă alias. Rețineți că nu am creat noi tipuri - am creat un alias pentru tipuri. 

Acestea pot fi la îndemână atunci când doriți să oferiți un înțeles mai bun sau semantic la tipurile în codbasele dumneavoastră Kotlin. Deci foloseste-le cu intelepciune! 

Concluzie

În acest tutorial, ați aflat mai multe despre programarea orientată pe obiecte în Kotlin. Am abordat următoarele:

  • clase abstracte
  • interfețe 
  • moştenire
  • tip alias

Dacă ați învățat Kotlin prin seria noastră Kotlin From Scratch, asigurați-vă că ați tastat codul pe care îl vedeți și îl rulați pe IDE. Un sfat excelent pentru a înțelege cu adevărat un nou limbaj de programare (sau orice concept de programare) pe care îl învățați este să vă asigurați că nu doar citiți resursele sau ghidul de învățare, ci și tastați codul real și executați-l!

În următorul tutorial din seria Kotlin From Scratch, veți fi prezentat în tratarea excepțiilor de la Kotlin. Ne vedem în curând!

Pentru a afla mai multe despre limba Kotlin, vă recomand să vizitați documentația Kotlin. Sau verificați câteva dintre celelalte postări pentru dezvoltarea aplicațiilor Android aici pe Envato Tuts!


Cod