CodeGym /Java Blog /Willekeurig /Toegangsmodificaties in Java
John Squirrels
Niveau 41
San Francisco

Toegangsmodificaties in Java

Gepubliceerd in de groep Willekeurig
Hoi! In de les van vandaag maken we kennis met het concept van toegangsmodificatoren en bekijken we voorbeelden van hoe ermee te werken. Natuurlijk is 'kennismaken' niet helemaal juist: de meeste ken je al uit eerdere lessen. Laten we, voor het geval dat, ons geheugen van het belangrijkste punt opfrissen. Modifiers-toegang zijn meestal trefwoorden die de toegang tot verschillende delen van uw code regelen. Waarom 'meestal'? Omdat een van hen standaard is ingesteld zonder het gebruik van een trefwoord :) Java heeft vier toegangsmodificatoren. We zetten ze op volgorde van meest restrictief tot meest 'soepel':
  • privaat;
  • standaard (pakket zichtbaar);
  • beschermd;
  • openbaar.
Laten we ze allemaal eens bekijken en bepalen wanneer ze nuttig kunnen zijn. En we zullen voorbeelden geven :)

De privémodificator

Toegang tot modificaties.  Privé, beschermd, standaard, openbaar - 2private is de meest beperkende toegangsmodifier. Het beperkt de zichtbaarheid van gegevens en methoden tot binnen een enkele klasse. Je kent deze modifier uit de les over getters en setters. Herinner je je dit voorbeeld nog?

public class Cat {

   public String name;
   public int age;
   public int weight;

   public Cat(String name, int age, int weight) {
       this.name = name;
       this.age = age;
       this.weight = weight;
   }

   public Cat() {
   }

   public void sayMeow() {
       System.out.println("Meow!");
   }
}

public class Main {

   public static void main(String[] args) {

       Cat cat = new Cat();
       cat.name = "";
       cat.age = -1000;
       cat.weight = 0;
   }
}
We hebben er in een vorige les over nagedacht. We hebben hier een ernstige fout gemaakt: we maken onze gegevens openbaar, waardoor collega-programmeurs rechtstreeks toegang hebben tot de velden en hun waarden kunnen wijzigen. Sterker nog... deze waarden werden toegekend zonder enige controle. Dit betekent dat ons programma een kat kan creëren met de naam "" met een leeftijd van -1000 jaar en een gewicht van 0. Om dit probleem op te lossen, hebben we getters en setters gebruikt, en ook de private modifier gebruikt om de toegang tot de gegevens te beperken.

public class Cat {

   private String name;
   private int age;
   private int weight;

   public Cat(String name, int age, int weight) {
       this.name = name;
       this.age = age;
       this.weight = weight;
   }

   public Cat() {
   }

   public void sayMeow() {
       System.out.println("Meow!");
   }

   public String getName() {
       return name;
   }

   public void setName(String name) {
       // input parameter check
       this.name = name;
   }

   public int getAge() {
       return age;
   }

   public void setAge(int age) {
       // input parameter check
       this.age = age;
   }

   public int getWeight() {
       return weight;
   }

   public void setWeight(int weight) {
       // input parameter check
       this.weight = weight;
   }
}
Kortom, het beperken van de toegang tot velden en het implementeren van getters en setters zijn de meest voorkomende voorbeelden van hoe privézou worden gebruikt in het echte werk. Met andere woorden, het belangrijkste doel van deze modifier is om inkapseling in een programma te bereiken. Dit geldt trouwens niet alleen voor velden. Stel je voor dat je programma een methode heeft die een aantal ZEER complexe functionaliteit implementeert. Wat kunnen we als voorbeeld voorstellen? Stel dat uw methode readDataFromCollider() een gegevensadres als invoer accepteert, gegevens uit de Large Hadron Collider in byteformaat leest, deze gegevens omzet in tekst, naar een bestand schrijft en afdrukt. Zelfs een beschrijving van de methode ziet er angstaanjagend uit, om nog maar te zwijgen van de code :) Om de code leesbaarder te maken, is het het beste om niet alle complexe logica van de methode op één plaats te schrijven. In plaats daarvan zouden we de functionaliteit moeten opsplitsen in afzonderlijke methoden. Bijvoorbeeld de readByteData()methode is verantwoordelijk voor het lezen van gegevens, de methode convertBytesToSymbols() converteert de gegevens die zijn gelezen van de collider naar tekst, de methode saveToFile() slaat de ontvangen tekst op in een bestand en de methode printColliderData() drukt ons gegevensbestand af. Uiteindelijk zal onze methode readDataFromCollider() veel eenvoudiger zijn:

public class ColliderUtil {

   public void readDataFromCollider(Path pathToData) {
       byte[] colliderData = readByteData(pathToData);
       String[] textData = convertBytesToSymbols(colliderData);
       File fileWithData = saveToFile(textData);
       printColliderData(fileWithData);
   }

   public byte[] readByteData(Path pathToData) {

       // Reads data in bytes
   }

   public String[] convertBytesToSymbols(byte[] colliderDataInBytes) {

       // Converts bytes to characters
   }

   public File saveToFile(String[] colliderData) {

       // Saves read data to a file
   }

   public void printColliderData(File fileWithColliderData) {

       // Prints data from the file
   }
}
Zoals u zich echter herinnert uit de les over interfaces, krijgt de gebruiker alleen toegang tot de externe interface. En onze 4 methodes horen daar niet bij. Het zijn hulpmethoden: we hebben ze gemaakt om de leesbaarheid van de code te verbeteren en om niet vier verschillende taken in één methode te proppen. U hoeft de gebruiker geen toegang tot deze methoden te geven. Als gebruikers toegang hebben tot de methode convertBytesToSymbols() wanneer ze met de collider werken, zullen ze hoogstwaarschijnlijk gewoon in de war raken door de methode en zich afvragen waar het voor is. Welke bytes worden omgezet? Waar komen ze vandaan? Waarom ze naar tekst converteren? De logica die in deze methode wordt uitgevoerd, maakt geen deel uit van de interface die aan de gebruiker wordt getoond. Alleen de readDataFromCollider()methode maakt deel uit van de interface. Dus wat doen we met deze vier 'interne' methoden? Rechts! Gebruik de privé- modifier om de toegang tot hen te beperken. Hierdoor kunnen ze rustig hun werk binnen de klas uitvoeren zonder de gebruiker in verwarring te brengen, die de logica van elke individuele methode niet hoeft te kennen.

public class ColliderUtil {

   public void readDataFromCollider(Path pathToData) {
       byte[] colliderData = readByteData(pathToData);
       String[] textData = convertBytesToSymbols(colliderData);
       File fileWithData = saveToFile(textData);
       printColliderData(fileWithData);
   }

   private byte[] readByteData(Path pathToData) {
       // Reads data in bytes
   }

   private String[] convertBytesToSymbols(byte[] colliderDataInBytes) {
       // Converts bytes to characters
   }

   private File saveToFile(String[] colliderData) {
       // Saves read data to a file
   }

   private void printColliderData(File fileWithColliderData) {
       // Prints data from the file
   }
}

De beschermde modifier

De volgende meest beperkende modifier is beschermd . Toegang tot modificaties.  Privé, beschermd, standaard, openbaar - 3Velden en methoden gemarkeerd door de beschermde toegangsmodifier zullen zichtbaar zijn:
  • binnen alle klassen inbegrepen in hetzelfde pakket als het onze;
  • binnen alle klassen die onze klasse erven.
In het begin is het moeilijk voor te stellen wanneer dit nodig zou kunnen zijn. Wees niet verbaasd: er zijn veel minder use cases voor protected dan voor private , en ze zijn heel specifiek. Stel je voor dat we een abstracte klasse AbstractSecretAgent hebben die een geheim agent vertegenwoordigt in een of andere inlichtingendienst, evenals een pakket top_secret dat deze klasse en zijn afstammelingen bevat. Concrete klassen zoals FBISecretAgent , MI6SecretAgent , MossadSecretAgent , etc. erven het. Binnen de abstracte klasse willen we een agentteller implementeren. Het zal toenemen wanneer ergens in het programma een nieuwe agent wordt aangemaakt. pakket top_secret;

public abstract class AbstractSecretAgent {

   public static int agentCount = 0;
}
Maar onze agenten zijn geheim! Dit betekent dat zij en niemand anders mogen weten hoeveel van hen er zijn. We kunnen de beschermde modifier eenvoudig toevoegen aan het veld agent_counter . Dan kunnen instanties van andere geheime agentklassen en andere klassen in ons top_secret- pakket hun waarde krijgen.

public abstract class AbstractSecretAgent {

   protected static int agent_counter = 0;
}
En dat is het soort gespecialiseerde taak waarvoor de beschermde modifier nodig is :)

De zichtbare modifier van het pakket

De volgende op de lijst is de standaardmodifier , ook wel bekend als de zichtbare modifier van het pakket. Het wordt niet aangegeven door een trefwoord, aangezien Java het standaard toepast op alle velden en methoden. Als je het volgende in je code schrijft:

int x = 10
de variabele x zal dit pakket zichtbare toegang hebben . Het is gemakkelijk te onthouden wat het doet. Kortom, standaard = beschermde overerving :) Net als de beschermde modifier is de toepassing ervan beperkt. Meestal wordt standaardtoegang gebruikt in een pakket dat enkele hulpprogrammaklassen heeft die niet de functionaliteit van alle andere klassen in het pakket implementeren. Laten we een voorbeeld geven. Stel je voor dat we een pakket 'services' hebben. Het bevat verschillende klassen die werken met een database. Er is bijvoorbeeld een klasse UserService die gebruikersgegevens uit de database leest, een CarServiceklasse die autogegevens uit dezelfde database leest, en andere klassen, die elk met specifieke typen objecten werken en overeenkomstige gegevens uit de database lezen.

package services;

public class UserService {
}

package services;

public class CarService {
}
Maar het zou gemakkelijk zijn als de gegevens in de database in het ene formaat zijn en we hebben het in een ander formaat nodig. Stel je voor dat de geboortedata van gebruikers in de database worden opgeslagen als <TIMESTAMP WITH TIME ZONE>...

2014-04-04 20:32:59.390583+02
...en in plaats daarvan hebben we het eenvoudigste object nodig - een java.util.Date . Om dit probleem op te lossen, kunnen we binnen het servicespakket een speciale Mapper- klasse maken . Het zal verantwoordelijk zijn voor het omzetten van gegevens uit de database naar onze vertrouwde Java-objecten. Een eenvoudige helperklasse. Gewoonlijk verklaren we alle klassen als openbare klasse ClassName , maar dit is geen vereiste. We kunnen onze helperklasse eenvoudig declareren als klasse Mapper . In dit geval doet het nog steeds zijn werk, maar is het niet zichtbaar voor iemand buiten het dienstenpakket !

package services;

class Mapper {
}


package services;

public class CarService {

   Mapper mapper;
}
En hier is de basisredenering: waarom zou iemand buiten een pakket een helperklasse moeten zien die alleen werkt met de klassen in dat pakket?

De openbare modifier

En last but not least, de openbare modifier! Je ontmoette deze modifier op je eerste studiedag op CodeGym, de eerste keer dat je public static void main(String[] args) uitvoerde . Nu je de les over interfaces hebt bestudeerd, is het doel voor jou duidelijk :) De publicToegang tot modificaties.  Privé, beschermd, standaard, openbaar - 4 modifier is tenslotte gemaakt om gebruikers iets te geven. Bijvoorbeeld de interface van uw programma. Stel dat je een vertaalprogramma hebt geschreven dat Russische tekst in het Engels kan vertalen. Je hebt een translate(String textInRussian) methode gemaakt die alle noodzakelijke logica implementeert. Je hebt deze methode gemarkeerd met het woord public , en nu maakt het deel uit van de interface:

public class Translator {

   public String translate(String textInRussian) {

       // Translates text from Russian to English
   }
}
U kunt deze methode binden aan de knop 'Vertalen' op het scherm en u bent klaar! Iedereen kan het gebruiken. De delen van de code gemarkeerd met de public modifier zijn bedoeld voor de eindgebruiker. Om een ​​realistisch voorbeeld te geven: privé is voor alle processen die binnen een tv plaatsvinden, maar openbaar is voor de knoppen op de afstandsbediening die worden gebruikt om de tv te beheren. Bovendien hoeft de gebruiker niet te weten hoe de televisie in elkaar zit of werkt. De afstandsbediening is de set van publieke methoden: on() , off() , nextChannel() , previousChannel() , gainVolume() , afnameVolume() etc. Om te versterken wat je hebt geleerd, raden we je aan een videoles van onze Java-cursus te bekijken
Opmerkingen
TO VIEW ALL COMMENTS OR TO MAKE A COMMENT,
GO TO FULL VERSION