Bent u bekend met de term 'spaghetti code'? Dit is een metafoor die je misschien zou kunnen horen van niet-JavaScript-ontwikkelaars in kritiek op de taal. Het is code zonder structuur. Het zal bestaan uit regel na regel met uitspraken. Sommigen kunnen zijn ingepakt in functies, sommige helemaal niet. En als je geluk hebt, zitten alle 9.000 regels code in één bestand. Deze "spaghetti" -structuur is waarschijnlijk het resultaat van procedurele programmering.
Bij procedureel programmeren worden functies gebruikt om taken uit te voeren. We hebben functies nodig, maar we hebben ook een ontwerp nodig waarmee we kunnen werken. En hoewel spaghetti geweldig is voor het avondeten, is het niet voor code. Het tegengif is objectgeoriënteerd programmeren. Om objectgeoriënteerd programmeren te begrijpen, behandelen we het ontwerpen van een programma, het definiëren van klassen en het maken van objecten.
Laten we ons voorstellen dat je de taak hebt gekregen om een aanvraag voor een boekwinkel te maken. Gewoon voor de lol, laten we onze boekhandel Amazonia bellen. Amazonia zal boeken hebben. Er zijn beoordelingen voor boeken. En we willen boeken opzoeken van de auteur. Er zullen meer functies zijn die we in onze app willen implementeren, maar dit is genoeg voor nu.
Objectgeoriënteerd programmeren is gecentreerd op het maken van objecten. Dus hoe gaan we om met het vertalen van deze vereisten naar objecten? Eén techniek is om een lijst van de zelfstandige naamwoorden uit onze beschrijving te maken en vervolgens de lijst te verfijnen tot die welke relevant zijn voor het probleem. We noemden de volgende zelfstandige naamwoorden in ons probleem:
Toepassing is een irrelevant zelfstandig naamwoord, dus het kan worden weggegooid. We kunnen ook van de boekwinkel afkomen, omdat deze vergelijkbaar is met de toepassing. Als we iets moesten doen met meerdere boekwinkels, dan zouden we het kunnen houden. We blijven achter met boeken, recensies en auteurs. (Auteurs zijn meervoudig omdat we in deze applicatie meerdere auteurs hebben.)
Laten we nu kijken naar hoe we elke klas zullen ontwerpen. Een klas is een blauwdruk voor het maken van objecten. De boekklasse die we maken, biedt ons een blauwdruk voor het maken van boekobjecten.
Het is vergelijkbaar met hoe een architect een blauwdruk gebruikt om huizen te maken. De blauwdruk toont de slaapkamers, badkamers, de keuken en de woonkamer. Van deze blauwdruk kunnen veel huizen worden gemaakt. Ze hoeven echter niet allemaal hetzelfde te zijn. Elk huis kan worden aangepast door bijvoorbeeld de verf, de vloer of de armaturen te verwisselen.
Schrijf de klassen die u zou gebruiken voor een winkelwagentje-programma. Het winkelwagentje zou het volgende moeten kunnen doen:
Om onze boekenklas te ontwerpen, moeten we nadenken over wat de klas moet doen om te weten en waarvoor hij verantwoordelijk is. Voor een boek moeten we de titel, de auteur en het ISBN kennen. Dit zijn onze gegevensattributen.
Sommige dingen die de klas moet kunnen doen zijn de titel ophalen en instellen, de auteur ophalen en instellen en het ISBN-nummer ophalen en instellen. Dit zullen de methoden van de klas zijn. Hier is wat onze boekklasse eruit zou moeten zien gezien onze vereisten:
klasboek constructor (titel, auteur, isbn) this.title = title; this.author = auteur; this.isbn = isbn; getTitle () return this.title; setTitle (newTitle) this.title = newTitle; getAuthor () retourneer dit.auteur; setAuthor (newAuthor) this.author = newAuthor; getIsbn () return this.isbn; setIsbn (newIsbn) this.isbn = newIsbn;
Bij conventie wordt de klassenaam met een hoofdletter geschreven. De constructor is een speciale functie die de gegevensattributen declareert en initialiseert. Binnen de constructorfunctie worden attributen toegevoegd met behulp van de deze
trefwoord. Vervolgens worden alle methoden van de klasse vermeld zonder scheidingstekens.
Methoden die beginnen met krijgen
staan bekend als accessormethoden omdat ze een waarde retourneren. Methoden die beginnen met reeks
zijn mutator-methoden omdat ze een waarde opslaan of de waarde van een attribuut veranderen.
Dit is de algemene vorm voor het definiëren van een klasse:
class ClassName constructor (... args) this.attr = arg1; this.attr2 = arg2; ... methodOne () ... methodTwo () ...
Een klasse kan ook worden gedeclareerd met behulp van deze syntaxis:
const ClassName = class ...
Klassen kunnen ook statische methoden hebben. Een statische methode is een methode die een eigenschap van de klasse is, niet het object. Laten we zeggen dat we een statische methode voor onze boekklasse willen maken om id's te genereren. Dit is de syntaxis:
class Book constructor () ... static generId () ...
Om de methode te bellen:
Book.generateId ();
Een natuurlijke vraag zou zijn wanneer en waarom zou u een statische methode gebruiken? Ik kan niet zeggen dat ik een goede reden ken om statische methoden te gebruiken. Het hangt er vanaf hoe je je klas ontwerpt. Een statische methode kan worden gebruikt als een hulpmethode voor uw objecten, maar dan kunnen dergelijke functies in hun eigen klasse worden opgeslagen. Als u een goed use-case weet, laat dan uw mening achter in de comments.
Ten slotte moet je voor de organisatie een klasse opslaan als een module. Een module is slechts een bestand dat uw code bevat. Om onze boekenklas in een module te maken, voegen we een exporteren
verklaring ervoor.
exportklasse boek ...
Om de klasse Book in een ander bestand te gebruiken, importeren we het.
importeer Boek vanuit Boek
Waar de bevat de waarden die zijn geëxporteerd uit de module, en
van boek
is een verwijzing naar het bestand Book.js.
Definieer een klasse voor auteurs en recensies.
De klasse op zichzelf is nutteloos voor ons tenzij we er iets mee doen. We willen boeken maken. Om dat te doen, moeten we de klas instantiëren. Instantiëren is de technische term voor het maken van nieuwe objecten. We noemen het object dat is gemaakt van de klasse een instantie. Dit is hoe we een nieuw exemplaar van een boek zouden maken:
let book = new Book ("Great Expectations", "Charles Dickens", 1234); book.getTitle () // Great Expectations
Objecten moeten worden geïnstantieerd met de nieuwe
operator. De gegevens die in het object worden ingevoerd, zijn de parameters die we in onze constructor hebben gedefinieerd. Dit is de algemene vorm voor het instantiëren van een klasse:
variableName = new ClassName (... args);
Stel dat we kenmerken willen toevoegen aan onze boekenklasse, zoals een ID, prijs en het aantal dat op voorraad is. We hebben nu zes parameters in onze constructor en dat is niet mooi. Het is niet alleen slecht om naar te kijken. Het creëert extra inspanning voor ontwikkelaars die de klas gebruiken, omdat ze de volgorde van de argumenten moeten kennen. Een betere oplossing is om een object als argument door te geven. Voorbeeld:
class Book constructor (data) this.id = data.id; this.title = data.title; this.author = data.author; this.isbn = data.isbn; this.units = data.units; this.price = data.price; getTitle () return this.title; ...
Om het object te instantiëren:
laat gegevens = id: 1, titel: "Great Expectations", auteur: "Charles Dickens", isbn: 1234, eenheden: 10, prijs: 29,95 laat boek = nieuw boek (gegevens);
In ons voorbeeld hadden we de titel ook kunnen gebruiken met de verklaring boek titel
omdat alle kenmerken in de klas openbaar zijn. Nu vraag je je misschien af waarom ik al deze methoden heb gemaakt als we direct toegang hebben tot de kenmerken. Was het alleen om u de syntaxis te laten zien? Ja. Ik wil ook de voordelen laten zien van het organiseren van uw code op deze manier.
Het bundelen van gerelateerde code in een object staat bekend als encapsulation. Een van de voordelen van inkapseling is het verbergen van gegevens. Gegevens verbergen betekent dat de kenmerken van een object niet buiten de klas kunnen worden geopend.
In andere talen, zoals Java en Python, kunnen we privékenmerken en privémethoden hebben. Omdat al onze gegevens standaard openbaar zijn in een JavaScript-klasse, kunnen we geen gebruik maken van deze functie. Toch moeten we toegang krijgen tot onze gegevens met getters en setters. Eén conventie is om een kenmerk met een onderstrepingsteken te prefixen _
om aan te geven dat het privé is.
Maak een boekobject dat een auteurobject gebruikt om het auteursattribuut in te stellen.
We hebben geleerd dat een klasse een blauwdruk is voor het maken van objecten en dat een object een instantie van een klasse is. Het voordeel van het bouwen van software in objecten is dat het een programmastructuur geeft en het beter beheersbaar maakt.
Wanneer we een groot programma hebben, kan het opsplitsen in objecten ervoor zorgen dat de onderdelen onafhankelijk van andere onderdelen worden ontwikkeld en onderhouden. Met deze modulariteit komt herbruikbaarheid. Omdat onze code is ingekapseld, kunnen de objecten steeds opnieuw worden gebruikt in andere delen van het programma. Plus we hebben een eenheid code die toetsbaar is. Hoe beter onze code is, hoe veiliger het is voor bugs.