een dataklasse is een concept dat niet gebonden is aan een specifieke programmeertaal, het is een patroon dat handig genoeg is voor de meeste programmeurs als een eenvoudige manier om informatie te representeren, in te kapselen en te verplaatsen.

een gegevensklasse verwijst naar een klasse die alleen velden en crud-methoden bevat om ze te benaderen (getters en setters). Dit zijn gewoon containers voor gegevens die door andere klassen worden gebruikt. Deze klassen bevatten geen extra functionaliteit en kunnen niet onafhankelijk werken op de gegevens die zij bezitten.

gewoonlijk vertegenwoordigen gegevensklassen reële entiteiten, en het is gebruikelijk om tientallen of honderden van deze klassen in een project te hebben, wat betekent dat het maken, wijzigen en manipuleren van deze objecten een veel voorkomende taak is voor een ontwikkelaar.

een Gegevensklasse in Java

zo ziet een gegevensklasse er gewoonlijk uit in Java:

u zult merken dat we de methoden toString() , equals() en hashCode() overschrijven (gedeclareerd in de klasse Object.java). Waarom is het overschrijven van deze methoden relevant in gegevensklassen?

bij de implementatie van deze drie methoden creëren we waardeobjecten, klassen waarvoor elke twee instanties met voldoende gelijke veldwaarden als uitwisselbaar worden beschouwd. (OPMERKING: Om volledig waar te zijn, moeten we de klasse onveranderlijk te maken. Het maken van de velden definitief en het verwijderen van de setters helpt. Onveranderlijkheid wordt vaak als een goede praktijk beschouwd en indien mogelijk aanbevolen)

  • equals() : standaard geeft true alleen terug als de twee variabelen naar hetzelfde object verwijzen, d.w.z. als de positie in het geheugen hetzelfde is. We negeren deze methode voor het retourneren van true als de objecten dezelfde informatie bevatten, met andere woorden als de objecten dezelfde entiteit vertegenwoordigen. Het controleert de eigenschappen zijn hetzelfde en ze bevatten dezelfde waarde.
  • hashCode() : retourneert standaard het geheugenadres van het object in hexadecimaal. Het is een numerieke waarde om een object te identificeren tijdens het testen van gelijkheid, d.w.z. gelijke objecten hebben dezelfde hash code. Deze methode moet worden overschreven wanneer toString() wordt overschreven, zodat het een hashcode retourneert die wordt berekend uit de waarden van de eigenschappen.
  • toString(): Standaard retourneert het objecttype en de hashCode(), bijvoorbeeld [email protected]+ . We overschrijven deze methode om een meer voor mensen leesbare versie van het object te hebben, zoals User(name=Steve, surname=Jobs) .

ondanks het feit dat het zo ‘ n belangrijk concept is, is er niets in de bovenstaande Java-code dat deze klasse anders maakt dan alle andere. Programmeurs kunnen het herkennen als een dataklasse vanwege de klassenstructuur en patronen, maar vanuit het oogpunt van de compiler is deze klasse gewoon een andere klasse.

het maken van gegevensklassen is zo gebruikelijk dat ontwikkelaars vaak de IDE en andere plugins gebruiken om hen te helpen met deze repetitieve taak. De pijn van het maken van een data class in Java kan worden verlicht door plugins of de IDE, maar de meeste bugs worden geïntroduceerd op verdere wijzigingen van deze klassen. Het is heel gemakkelijk om te vergeten om alle metgezel methoden dienovereenkomstig te wijzigen elke keer dat een veld is verwijderd of toegevoegd.

een dataklasse in Java mist taalondersteuning. Het is een repetitieve en bug-gevoelig taak die te veel wrijving voor een moderne programmeertaal vertegenwoordigt.

een gegevensklasse in Kotlin

dezelfde gegevensklasse in Kotlin zou er ongeveer zo uitzien:

data class User(var name: String, var age: Int)

Kotlin verheft gegevensklassen tot eersteklas burgers met het data sleutelwoord. Laten we het afbreken.

  • Getters en setters

de getters en setters worden automatisch aangemaakt in Kotlin wanneer we eigenschappen declareren. In het kort betekent var name: String dat de klasse User een eigenschap heeft die openbaar is (standaard zichtbaarheid in Kotlin), veranderlijk is (var) en een String type is. Gegeven dat het publiek is creëert het de getter, en gegeven dat is veranderlijk creëert het de setter.

als we de klasse alleen-lezen (geen setters) willen maken, moeten we val :

data class User(val name: String, val age: Int)

we kunnen val en var mengen in dezelfde klasse declaratie. U kunt val zien als een variabele final in Java.

alles is tot nu toe uitgelegd, het is gebruikelijk om elke klasse declaratie in Kotlin, maar het data sleutelwoord is wat hier een verschil maakt.

  • het data sleutelwoord

het declareren van een class als een data class zorgt ervoor dat we toString() , hashCode() en equals() automatisch implementeren op dezelfde manier als hierboven beschreven voor de Java class. Dus als we een user class maken zoals User("Steve Jobs",56) en de toString() methode aanroepen krijgen we iets als:User(name=Steve Jobs, age=56) .

destructieve declaraties

het data sleutelwoord biedt functies die destructieve declaraties toestaan. Kortom, het creëert een functie voor elke eigenschap zodat we dit soort dingen kunnen doen:

kopieerfunctie

het data sleutelwoord geeft ons een handige manier om klassen te kopiëren en de waarde van sommige eigenschappen te veranderen. Als we een kopie willen maken van een gebruiker die de leeftijd verandert, is dit de manier waarop we het zouden doen:

eigenschappen gedeclareerd in de klasse body worden genegeerd

de compiler gebruikt alleen de eigenschappen gedefinieerd in de primaire constructor voor de automatisch gegenereerde functies.

de eigenschap address het zal niet behandeld worden met het data sleutelwoord, dus het betekent dat de automatisch gegenereerde implementaties het zullen negeren.

paar en drievoudige

Pair en Triple zijn standaard gegevensklassen in de bibliotheek, maar de Kotin docs zelf ontmoedigen het gebruik ervan ten gunste van meer leesbare en op maat gemaakte gegevensklassen.

eisen en beperkingen

  • een gegevensklasse-constructor moet ten minste één parameter hebben.
  • alle parameters moeten in de handel worden gebracht als val of var .
  • een gegevensklasse kan nietabstract, open, sealed of inner .
  • equals , toString en hashCode methoden kunnen expliciet worden overschreven.
  • expliciete implementaties voor componentN() en copy() functies zijn niet toegestaan.
  • het afleiden van een gegevensklasse van een type met een copy() functie-overeenkomende handtekening werd verouderd in Kotlin 1.2 en was verboden in Kotlin 1.3.
  • a data klasse kan niet worden uitgebreid van een andere data klasse.
  • a data klasse kan andere klassen uitbreiden (sinds Kotlin 1.1)

Dataklassen zijn eersteklas burgers in Kotlin. In een zeer korte syntaxis bieden ze een wrijvingsloze oplossing met alle voordelen en geen compromissen.

wat betekent het voor Android

ik ga proberen uit te leggen wat de belangrijkste voordelen zijn die Ik heb gevonden met behulp van Kotlin-gegevensklassen in mijn Android-projecten. Dit zijn niet allemaal en misschien niet de belangrijkste, maar dit zijn de meest voor de hand liggende uit mijn ervaring tot nu toe.

  • Data modellen

architectuur in Android was (en is nog steeds) een hot topic. Er zijn meerdere opties, maar de meeste van hen hebben gemeen de scheiding van zorgen en single responsibility principes. Clean Architecture – zeer beroemd in de Android – Gemeenschap-is een reeks goede praktijken te volgen bij het streven naar een goede architectuur die de nadruk legt op het gebruik van verschillende modellen voor verschillende lagen van de architectuur. Dit betekent dat een project met 3 of 4 verschillende datamodellen standaard wordt.

dat betekent dat het aantal dataklassen in een project zeer hoog is, en operaties zoals maken, lezen, wijzigen, kopiëren, vergelijken, toewijzen… datamodelklassen zijn dagelijkse taken die profiteren van de Autogegenereerde code van de Dataklasse van Kotin. Bespaart een enorme hoeveelheid tijd en vermindert de mogelijkheden om bugs te introduceren.

  • Geen Auto-waarde meer

het gebruik van waardetypen is een goede praktijk die zeer uitgebreid is in Android, vooral onder dataklassen.

een waardetype is een object uit een onveranderlijke waardeklasse.
een waardeklasse is een klasse waarvoor gelijkheid afhankelijk is van de inhoud ervan.
een onveranderlijke klasse is een klasse die niet gewijzigd kan worden na de creatie.

AutoValue is een populaire bibliotheek van Google die ons helpt om waarde types te creëren. Het doet zijn werk, maar het is zeer uitgebreid voor iets dat niet zo ingewikkeld zou moeten zijn.

met behulp van de kotlin data klassen met de val access modifier geven we een benadering die dicht genoeg bij de waarde types.

data class User(val name : String, val age : Int)

de vorige gebruikersklasse is een klasse die dicht genoeg bij waardetypen ligt, in een veel kortere syntaxis. Voor een goed deel van de mensen, AutoValue kan worden vervangen door Kotlin. Minder code, geen annotatieverwerking, en een bibliotheek minder om op te vertrouwen.

opmerking: Kotlin biedt alleen-lezen eigenschappen en klassen met het val sleutelwoord. Alleen-lezen en onveranderlijk is niet hetzelfde (meer hier) maar in het algemeen, wordt beschouwd als goed genoeg voor praktische doeleinden.

  • niet meer Lombok

een van de manieren waarop ontwikkelaars tijd probeerden te besparen bij het omgaan met gegevensklassen is het gebruik van bibliotheken om getter en setter methoden te genereren. Lombok is een van de (on)bekende in Android / Java. Het vereist niet alleen de bibliotheek, maar ook een plugin voor als. Het lange verhaal kort is voor de meeste ontwikkelaars Lombok brengen zo veel voordelen als hoofdpijn, dus het wordt dat bibliotheek je begint te houden, maar na een tijdje, je kunt niet wachten om zich te ontdoen van, maar je nooit doen, want is overal.

aangezien Kotlin Gegevensklassen niet nodig hebben om handmatig getter / setter methoden te schrijven, is de belangrijkste behoefte voor Lombok verdwenen.

  • RecyclerView DiffUtil

RecyclerView in Android is de widget. Het staat in elke app op meerdere schermen. Een belangrijk onderdeel bij de implementatie van RecyclerView-adapters is de DiffUtil-klasse. DiffUtil berekent het verschil tussen twee lijsten om de eventuele wijzigingen naar de adapter te verzenden. Het is veel efficiënter dan het vernieuwen van de hele lijst over en weer, en het animeert de veranderingen prachtig.

DiffUtil is sterk afhankelijk van de gelijkheid van de items, wat betekent dat twee items hetzelfde zijn wanneer hun inhoud hetzelfde is. Elke keer dat u een RecyclerView gebruikt, moet u DiffUtil gebruiken, wat betekent dat u een manier nodig hebt om te vergelijken of twee objecten dezelfde informatie bevatten. Dit is een van de redenen waarom we equals in onze Java Data classes moeten overschrijven, maar met Kotlin data classes is het gratis.

Opmerking: Als u niet vertrouwd bent met DiffUtil, raadpleeg dan deze snelstartgids.

  • Tests

in testklassen controleren we voortdurend of de verwachte waarden overeenkomen met de werkelijke waarden. Het vergelijken van objecten gelijkheid (zoals eerder beschreven) is een veel voorkomende taak.

zelfs als u de equals, toString en toHash triplet voor uw normale app-runtime niet hoeft te overschrijven, is de kans groot dat u deze methoden voor testdoeleinden moet overschrijven, dus Kotlin-gegevensklassen maken het pad naar testen vrij zonder excuses.

Addendum

laten we het hebben over enkele andere veelvoorkomende scenario ‘ s die het vermelden waard zijn bij het werken met Kotlin-gegevensklassen. Dit is niet strikt gerelateerd aan gegevens klassen, maar zijn vooral gebruikelijk onder hen.

  • meervoudige constructeurs
data class User(val name : String, val age : Int)

In de User klasse die we eerder hebben gedefinieerd, moeten we expliciet name en age specificeren bij het maken van een instantie als User("Steve", 56) .

in Kotlin kunnen we standaardwaarden voor argumenten zo definiëren dat als we geen waarde doorgeven voor dat argument, de standaardwaarde eraan wordt toegewezen.

data class User(val name : String, val age :Int = 0)

User("Steve", 56) is nog steeds geldig, maar nu is een tweede constructor User("Steve") toegestaan. In dat geval is de waarde age 0.

we kunnen standaardwaarden toewijzen aan beide parameters, waardoor een derde constructor User() wordt toegestaan, waarbij name leeg is en age 0.

data class User(val name : String = "", val age : Int = 0)

dus nu User(), User("Steve") en User("Steve",56) zijn alle geldige aanroepen.

dit heeft een aantal beperkingen: optionele parameters moeten de laatste parameters zijn in de constructor. De volgende zal niet compileren.

data class User(val name : String = "", val age : Int)
val user = User(56) // This doesn't compile

een andere beperking is dat als we meerdere optionele parameters hebben, ze moeten worden overgeslagen van rechts naar links.

data class User(
val name : String,
val surname : String = "",
val age : Int = 0
)User("Steve")
User("Steve", "Jobs")
User("Steve", "Jobs", 56)
User("Steve",56) // This wont compile

om met deze beperkingen om te gaan biedt Kotlin benoemde argumenten aan. Dit stelt ons in staat om te specificeren tot welk argument behoort tot elke waarde. Nu kunnen we dingen doen zoalsUser(name = "Steve", age = 56) – of korter User("Steve", age = 56) – waarbij de achternaam wordt toegewezen aan de standaardwaarde.

standaard argumenten en benoemde argumenten zijn een zeer handige manier om meerdere constructors en overbelasting van een zeer compacte declaratie aan te bieden.

  • @JvmOverloads

alles uitgelegd in het vorige punt is geen rekening te houden met oproepen van de Java-kant. Kotlin is interoperabel met Java, dus we moeten instances van de User klasse vanuit Java kunnen aanmaken.

als je het niet gaat gebruiken vanuit Java Dan ben je klaar, maar anders heb je de @JvmOverloads annotatie nodig, aangezien Java geen benoemde argumenten biedt.

data class User @JvmOverloads constructor(
val name : String,
val surname : String = "",
val age : Int = 0
)

wat doet het genereren van meerdere constructors zodat het vanuit Java kan worden aangeroepen.

Opmerking: Het is belangrijk op te merken dat het niet elke mogelijke permutatie zal aanmaken, maar degene die het resultaat zijn van het verwijderen van de optionele argumenten van rechts naar links. Meer hier

  • Builders

gezien Kotlin genoemde parameters en standaardargumenten biedt, maakt het minder waarschijnlijk dat bouwers nodig zijn. Op de top van dat, moderne IDEs zoals Android Studio al tonen de naam van de parameter aan de oproepende kant waardoor het gemakkelijker te lezen waardoor het minder interessant alleen voor leesbaarheid doeleinden.

in de gevallen waarin het builder-patroon nog steeds nodig is. Kotlin biedt niets speciaals om ons daarbij te helpen. Een bouwer patroon in Kotlin ziet eruit als:

  • annotaties

het is heel gebruikelijk voor sommige data model klassen om annotatie verwerking te gebruiken. Bijvoorbeeld API-modellen (dataklassen om deserialized reacties van de API weer te geven) worden vaak geannoteerd met Gson of Moshi annotaties. De persistence modellen (dataklassen om gegevens weer te geven die zijn opgeslagen in lokale opslag/databases) worden vaak geannoteerd met Room-of Realm-annotaties.

in Kotlin kunnen we die annotaties nog steeds gebruiken. Dit is bijvoorbeeld een gebruikersmodel dat in de Roomdatabase moet worden opgeslagen:

samenvatting

Kotlin data classes zijn het resultaat van jaren leren van pijn en frustratie met data classes in Java. Ze streven naar het hebben van alle voordelen en geen van de nadelen. Het gebruik ervan is heel eenvoudig en plezierig en als je er eenmaal aan gewend bent, is het erg moeilijk om terug te kijken.

in Android helpen ze ons op verschillende manieren, maar meestal besparen ze veel tijd en verminderen ze bugs.

een Kotlin data class is een goed voorbeeld van wat Kotlin is als programmeertaal: beknopt, pragmatisch en een plezier voor ontwikkelaars.

Geef een antwoord

Het e-mailadres wordt niet gepubliceerd.

lg