CodeGym/Java Blog/Willekeurig/OOP-concepten in Java
John Squirrels
Niveau 41
San Francisco

OOP-concepten in Java

Gepubliceerd in de groep Willekeurig
Een van de grootste sterke punten van Java is objectgeoriënteerd programmeren (OOP). Dat is de reden waarom deze taal zo populair is geworden en zeer geschikt is voor projecten van elke omvang. Wat is objectgeoriënteerd programmeren? Het is geen magie, maar het kan magisch lijken als je er echt in opgaat. OOP gaat over het bouwen van uw software. Het is een concept, of beter gezegd een aantal oeps-concepten in Java, waarmee u een aantal specifieke interacties en relaties tussen Java-objecten kunt creëren om effectief software te ontwikkelen en te gebruiken. OOP-concepten in Java - 1Klassieke OOP bevat 3 + 1 hoofdconcepten. Laten we beginnen met de klassiekers.

Het object

Zowel Java-objecten als objecten uit de echte wereld hebben twee kenmerken: toestand en gedrag.

Een menselijk object heeft bijvoorbeeld een staat (naam, geslacht, slapen of niet...) en gedrag (bestudeert Java, loopt, praat...). Elk Java-object slaat zijn status op in velden en onthult zijn gedrag door middel van methoden.

Inkapseling

Gegevensinkapseling is het verbergen van interne gegevens voor de buitenwereld en er alleen toegang toe krijgen via openbaar gemaakte methoden. Wat betekent dat? Welke gegevens? Verbergen voor wie? Verbergen betekent het beperken van directe toegang tot de gegevensleden (velden) van een klasse.

Hoe het werkt in Java:

  1. Velden zijn privé gemaakt
  2. Elk veld in een klasse krijgt twee speciale methoden: een getter en een setter. Getter-methoden retourneren de waarde van het veld. Met Setter-methoden kunt u de waarde van het veld op een indirecte maar toegestane manier wijzigen.

Voorbeeld van inkapseling in Java-code:

public class Student {
private int age;
private String name;

public int getAge() {
return age;
}

public void setAge(int age) {
this.age = age;
}

public String getName() {
return name;
}
public void setName(String name) {
this.name = name;
}
}

public class Test{
public static void main(String[] args) {
Student firstStudent = new Student();
firstStudent.setName("John");
// The name field is private, so you can no longer do this:  firstStudent.name = "John";
}
}

Waarom zou u inkapseling gebruiken?

De belangrijkste reden is om het gemakkelijker te maken om uw code te wijzigen. Stel je hebt een aanvraag voor een hockeyschool en er is een HockeyStudent- klas met twee velden die de naam en leeftijd van de student opslaan toen hij of zij zich inschreef op de school. Iets zoals dit:
public class HockeyStudent {
public String name;
public  int ageOfEnrollment;
}
Het veld ageOfEnrollment is openbaar, geen getters of setters... Deze klasse wordt door veel andere klassen gebruikt en alles was in orde totdat een ontwikkelaar besloot dat een enkel int-veld niet genoeg was. Sommige hockeyspelers in een cohort zijn bijna een jaar ouder dan hun leeftijdsgenoten, dus het zou handiger zijn om ze op te splitsen in twee groepen, afhankelijk van de maand waarin ze zijn geboren. Het veld ageOfEnrollment moet dus worden gewijzigd in een int-array (int[][]) : het eerste getal is voor volledige jaren en het tweede voor maanden. Nu moet je alle code refactoren die de Student- klasse gebruikt! Maar als uw ageOfEnrollmentveld privé is en je hebt getters en setters, dan is alles makkelijker. Als de vereiste voor het instellen van de leeftijd van een student verandert, update dan gewoon de logica in de setAgeOfEnrollment() setter-methode en je klassen kunnen Student zonder problemen blijven gebruiken! Dit voorbeeld is enigszins gekunsteld, maar ik hoop dat het verklaart waarom het gebruik van inkapseling een geweldig idee is.

Erfenis

Dit principe is gemakkelijker te begrijpen, zelfs zonder enige praktische ervaring. Herhaal jezelf niet (DROOG) zou het motto kunnen zijn voor het erfenisconcept. Met overerving kunt u een onderliggende klasse maken die de velden en methoden van de bovenliggende klasse overerft zonder ze opnieuw te definiëren. Natuurlijk kunt u de velden en methoden van de bovenliggende klasse overschrijven in de onderliggende klasse, maar dat is niet noodzakelijk. Bovendien kunt u nieuwe statussen en gedragingen toevoegen aan de onderliggende klasse. Bovenliggende klassen worden soms superklassen of basisklassen genoemd en onderliggende klassen worden subklassen genoemd. Java's extends -sleutelwoord wordt gebruikt om het principe van overerving in code te implementeren.

Hoe het werkt in Java:

  1. Maak de bovenliggende klasse.
  2. Maak de onderliggende klasse met behulp van het sleutelwoord extends .
  3. Gebruik in de constructor van de klasse Child de methode super(parentField1, parentField2, ...) om de velden van de ouder in te stellen.

Een constructor is een speciale methode die wordt gebruikt om een ​​nieuw gemaakt object te initialiseren. Een constructor heeft dezelfde naam als de klassenaam. Er zijn twee soorten constructors: standaard (no-arg constructor) en geparametriseerde constructor. Een klasse moet ten minste één constructor hebben (ze heeft de standaardconstructor als er geen andere constructors zijn gedefinieerd) en kan er veel hebben.

Telkens wanneer u een nieuw object maakt, roept u de constructor aan. In bovenstaand voorbeeld doe je dat in deze regel:

Student firstStudent = new Student();

U gebruikt het nieuwe trefwoord om de standaardconstructor van de klasse Student aan te roepen: tudent() .

Sommige regels:

  1. Een klas kan maar één ouder hebben.
  2. Eén bovenliggende klas kan meerdere onderliggende klassen hebben.
  3. Een kindklasse kan zijn eigen kindklassen hebben.

Voorbeeld van overerving in Java-code

Laten we een telefoonklasse maken .
public class Phone {
    int price;
    double weight;

// Constructor
public Phone(int price, double weight) {
        this.price = price;
        this.weight = weight;
    }

    void orderPhone(){
        System.out.println("Ordering phone...");
    }
}
Er zijn natuurlijk verschillende soorten telefoons, dus laten we twee onderliggende klassen maken: een voor Android-telefoons en een tweede voor iPhones. Vervolgens voegen we enkele velden en methoden toe die de ouder niet heeft. En we zullen super() gebruiken om constructors aan te roepen om de velden te initialiseren die de bovenliggende klasse wel heeft.

Voorbeeld van overerving op Java

public class Android extends Phone {

// Some new fields
String androidVersion;
int screenSize;

    String secretDeviceCode;

// Constructor
    public Android(int price, double weight, String androidVersion, int screenSize, String secretDeviceCode) {
        super(price, weight); // Android inherits Phone’s fields

        //this - reference to the current object
        //super - reference to the parent object

        this.androidVersion = androidVersion;
        this.screenSize = screenSize;
        this.secretDeviceCode = secretDeviceCode;
    }

	// New Android-specific method, does not exist in the Phone class
    void installNewAndroidVersion() {
        System.out.println("installNewAndroidVersion invoked...");

    }

}

public class IPhone extends Phone {

    boolean fingerPrint;

    public IPhone(int price, double weight, boolean fingerPrint) {
        super(price, weight);
        System.out.println("IPhone constructor was invoked...");
        this.fingerPrint = fingerPrint;
    }

    void deleteIPhoneFromDb() {
        System.out.println("deleteIPhoneFromDb invoked...");
    }

@Override // This is about polymorphism, see below
void orderPhone(){
        System.out.println("Ordering my new iPhone and deleting the old one...");
    }
}
Dus, om te herhalen: in Java kunt u met overerving een klasse uitbreiden met onderliggende klassen die de velden en methoden van de bovenliggende klasse erven. Het is een uitstekende manier om codeherbruikbaarheid te bereiken.

Polymorfisme

Polymorfisme is het vermogen van een object om te veranderen, verschillende vormen aan te nemen of liever op verschillende manieren te handelen. In Java vindt polymorfisme meestal plaats wanneer een verwijzing naar een bovenliggende klasse wordt gebruikt om naar een onderliggend klasseobject te verwijzen.

Wat dat betekent en hoe het werkt in Java:

Wat is polymorfisme op Java? Over het algemeen betekent dit dat u dezelfde methodenaam voor verschillende doeleinden kunt gebruiken. Er zijn twee soorten polymorfisme in Java: methode-overheersing (dynamisch polymorfisme) en methode-overbelasting (statisch polymorfisme).

Methode overheersend

U kunt de methode van een bovenliggende klasse overschrijven in een onderliggende klasse, waardoor deze op een andere manier moet werken. Laten we een bovenliggende klasse Musicus maken met een methode play() .

Voorbeeld van polymorfisme in Java-code

public class Musician {
    String name;
    int age;

    // Default constructor
    public Musician() {
    }

    // Parameterized constructor
    public Musician(String name, int age) {
        this.name = name;
        this.age = age;
    }

    void play() {
        System.out.println("I am playing my instrument...");
    }
}
Verschillende muzikanten gebruiken verschillende instrumenten. Laten we twee onderliggende klassen maken: Pianist en Violist . Dankzij polymorfisme voert elk zijn eigen versie van de methode play() uit . Bij overschrijven kunt u de annotatie @Override gebruiken , maar dit is niet noodzakelijk.
public class Pianist extends Musician {

    String favoritePianoType;

    public Pianist(String name, int age, String favoritePianoType) {
        super(name, age);
        this.favoritePianoType = favoritePianoType;
    }


    @Override
void play(){
        System.out.println("I am playing the piano...");
    }
}
De violist kan een solist zijn of een lid van een orkest. Laten we daar rekening mee houden bij het overschrijven van onze play() methode.
public class Violinist extends Musician {
    boolean isSoloist;

public Violinist(String name, int age, boolean isSoloist) {
            super(name, age);
            this.isSoloist = isSoloist;
        }


    @Override
void play(){
if (isSoloist)
        System.out.println("I am playing the violin solo...");
else
System.out.println("I am playing the violin in an orchestra...");

    }
}
Laten we een Demo- klasse maken, waarin we drie objecten zullen maken, één exemplaar van elk van de eerder gemaakte klassen. We zullen zien welke resultaten we krijgen.
public class Demo {
  public static void main(String[] args) {
  Musician musician = new Musician();
  Violinist violinist = new Violinist("John", 32, true);
  Pianist pianist = new Pianist("Glen", 30, "Acoustic");

  System.out.println("Musician said:");
  musician.play();
  System.out.println("Violinist said:");
  violinist.play();
  System.out.println("Pianist said:");
  pianist.play();
    }
}
Dit is wat we krijgen:
Musician said:
I am playing my instrument...
Violinist said:
I am playing the violin solo…
Pianist said:
I am playing the piano...
Elke violist en pianist is een muzikant, maar niet elke muzikant is een violist of pianist. Dat betekent dat u de afspeelmethode van de muzikant kunt gebruiken als u geen nieuwe hoeft te maken. Of u kunt de methode van de ouder vanuit het kind aanroepen met behulp van het sleutelwoord super . Laten we dat doen in de code van Pianist:
public class Pianist extends Musician {

    String favoritePianoType;

    @Override
    void play(){
        super.play();
        System.out.println("I am playing the piano...");
    }
}
Laten we nu onze methode main() in de klasse Demo aanroepen . Dit is het resultaat:
Musician said:
I am playing my instrument...
Violinist said:
I am playing the violin solo...
Pianist said:
I am playing my instrument...
I am playing the piano...

Methode overbelasting

Methode-overbelasting betekent het gebruik van verschillende methoden met dezelfde naam in dezelfde klasse. Ze moeten verschillend zijn wat betreft het aantal, de volgorde of het type van hun parameters. Stel dat een pianist zowel een akoestische piano als een elektrische piano kan spelen. Om elektrisch te spelen heeft de muzikant elektriciteit nodig. Laten we twee verschillende play()- methoden maken. De eerste zonder parameters, voor een akoestische piano, en de tweede met een parameter die aangeeft of er stroom beschikbaar is.
public class Pianist extends Musician {

    String name;
    int age;
    String favoritePianoType;

    @Override
    void play(){
        super.play();
        System.out.println("I am playing the piano...");
    }
    void play(boolean isElectricity){
        if (isElectricity) {
            System.out.println("The electricity is on.");
            System.out.println("I am playing the piano...");
        }
        else System.out.println("I can't play this without electricity.");
    }
}
Trouwens, je kunt de eerste methode play() binnen de tweede methode play(boolean) op deze manier gebruiken:
void play(boolean isElectricity){
        if (isElectricity) {
            System.out.println("The electricity is on.");
            play();
        }
        else System.out.println("I can't play this without electricity.");
    }
Laten we enkele regels toevoegen aan onze Demo- klasse om onze overbelasting te demonstreren:
public class Demo {
    public static void main(String[] args) {

        Musician musician = new Musician();
        Violinist violinist = new Violinist("John", 23, true);
        Pianist pianist = new Pianist("Glen", 30, "Acoustic");

        System.out.println("Musician said:");
        musician.play();
        System.out.println("Violinist said:");
        violinist.play();
        System.out.println("Pianist said:");
        pianist.play();
        System.out.println("The pianist will now try the electric piano:");
        pianist.play(true);
        System.out.println("The electricity has been shut off. Now when trying the electric piano, the pianist says:");
        pianist.play(false);
    }
}
Hier is het resultaat:
Musician said:
I am playing my instrument...
Violinist said:
I am playing the violin solo...
Pianist said:
I am playing my instrument...
I am playing the piano...
The pianist will now try the electric piano:
The electricity is on.
I am playing my instrument...
I am playing the piano...
The electricity has been shut off. Now when trying the electric piano, the pianist says:
I can't play this without electricity.
Java weet welke methode moet worden gebruikt op basis van de parameters en het objecttype. Dat is polymorfisme.

Abstractie

Wanneer we een klasse definiëren, proberen we ergens een model van te bouwen. Stel dat we een videogame schrijven met de naam MyRacer met verschillende raceauto's. Een speler kan er een kiezen en deze later bijwerken of een andere kopen. Dus... Wat is een auto? Een auto is behoorlijk ingewikkeld, maar als we een racevideogame proberen te maken (in tegenstelling tot een rijsimulator), hoeven we niet alle duizenden tandwielen en pakkingen te beschrijven die erin zitten. We hebben het model nodig, de topsnelheid, de wendbaarheid, de prijs, de kleur... En misschien is dat genoeg. Dat is het model van een auto voor ons spel. Stel dat we later in MyRacer 2 besluiten banden toe te voegen die de wegligging op de weg beïnvloeden. Hier is het model anders, omdat we meer details hebben toegevoegd. Laten' s definiëren data-abstractie als het proces van het identificeren van alleen de belangrijke (of noodzakelijke) kenmerken van een object en het negeren van irrelevante details. Er zijn verschillende abstractieniveaus. Als u bijvoorbeeld een passagier in een bus bent, moet u weten hoe uw bus eruit ziet en waar hij heen gaat, maar u hoeft niet te weten hoe u ermee moet rijden. Als u een buschauffeur bent, hoeft u niet te weten hoe u een nieuwe bus moet maken - u hoeft alleen te weten hoe u ermee moet rijden. Maar als u een busfabrikant bent, moet u naar een lager abstractieniveau gaan, omdat de details van het busontwerp erg belangrijk voor u zijn. Ik hoop dat je begrijpt wat ik bedoel. je moet weten hoe je bus eruit ziet en waar hij heen gaat, maar je hoeft niet te weten hoe je ermee moet rijden. Als u een buschauffeur bent, hoeft u niet te weten hoe u een nieuwe bus moet maken - u hoeft alleen te weten hoe u ermee moet rijden. Maar als u een busfabrikant bent, moet u naar een lager abstractieniveau gaan, omdat de details van het busontwerp erg belangrijk voor u zijn. Ik hoop dat je begrijpt wat ik bedoel. je moet weten hoe je bus eruit ziet en waar hij heen gaat, maar je hoeft niet te weten hoe je ermee moet rijden. Als u een buschauffeur bent, hoeft u niet te weten hoe u een nieuwe bus moet maken - u hoeft alleen te weten hoe u ermee moet rijden. Maar als u een busfabrikant bent, moet u naar een lager abstractieniveau gaan, omdat de details van het busontwerp erg belangrijk voor u zijn. Ik hoop dat je begrijpt wat ik bedoel.

Hoe het werkt in Java:

Laten we vier abstractieniveaus bouwen in Java, of beter gezegd in OOP - van de laagste (de meest specifieke) tot de hoogste (de meest abstracte).
  1. Het laagste abstractieniveau is een specifiek object. Het is een entiteit met een reeks kenmerken die tot een specifieke klasse behoren. Het heeft specifieke veldwaarden

  2. Een sjabloon voor het maken van objecten is een klasse. Het is een beschrijving van een set objecten met vergelijkbare eigenschappen en interne structuur.

  3. Een abstracte klasse is een abstracte beschrijving van de kenmerken van een reeks klassen (het fungeert als een sjabloon voor overerving door andere klassen). Het heeft een hoog abstractieniveau, dus het is onmogelijk om objecten rechtstreeks vanuit een abstracte klasse te maken. Alleen onderliggende klassen van abstracte klassen kunnen worden gebruikt om objecten te maken. Een abstracte klasse kan methoden bevatten met een implementatie, maar dit is geen vereiste.

  4. Een interface is een constructie van de Java-programmeertaalconstructie die alleen abstracte openbare methoden en statische constante velden bevat (laatste statische). Met andere woorden, noch abstracte klassen noch interfaces kunnen worden gebruikt om objecten te genereren.

Trouwens, in Java 8 of later kunnen interfaces niet alleen abstracte methoden en constanten hebben, maar ook standaard en statische methoden. In Java definieert een interface een gedrag, terwijl een abstracte klasse wordt gebruikt om een ​​hiërarchie te creëren. Eén interface kan worden geïmplementeerd door meerdere klassen.

Voorbeeld van een interface in Java-code

interface Human {
	public void struggle();
	public void protect();
}

interface Vulcan {
	int angleOfPointyEars;
	public void turnOffEmotions(boolean isOn);
	public void telepathy();
}
U kunt meer dan één interface implementeren
The Spock class implements Human and Vulcan {
public void struggle() {
System.out.println("I am struggling...");
}
	public void protect() {
System.out.println("You are under my protection!);
}
public void turnOffEmotions(boolean isOn){
If (isOn) {
System.out.println("I am turning off my emotions.");
isOn= !isOn;
}
}
	public void telepathy() {
System.out.println("Connecting to your brain...");
}

}
Voor beginnende studenten omvat dat alle hoofdconcepten van objectgeoriënteerd programmeren in Java. Naast de 4 belangrijkste OOP-principes, kent Java ook associatie, aggregatie en compositie. Je kunt ze "aanvullende OOP-principes" noemen. Ze verdienen hun eigen aparte artikel.
Opmerkingen
  • Populair
  • Nieuw
  • Oud
Je moet ingelogd zijn om opmerkingen te kunnen maken
Deze pagina heeft nog geen opmerkingen