CodeGym /Java blog /Tilfældig /OOP-koncepter i Java
John Squirrels
Niveau
San Francisco

OOP-koncepter i Java

Udgivet i gruppen
En af Javas største styrker er objektorienteret programmering (OOP). Det er grunden til, at dette sprog er blevet så populært og er velegnet til projekter af enhver størrelse. Hvad er objektorienteret programmering? Det er ikke magi, men det kan virke magisk, hvis du virkelig går ind i det. OOP handler om, hvordan du bygger din software. Det er et koncept, eller rettere en masse oop-koncepter i Java, som giver dig mulighed for at skabe nogle specifikke interaktioner og relationer mellem Java-objekter for effektivt at udvikle og bruge software. OOP-koncepter i Java - 1Klassisk OOP omfatter 3 + 1 hovedkoncepter. Lad os starte med klassikerne.

Objektet

Java-objekter såvel som objekter i den virkelige verden har to karakteristika: tilstand og adfærd.

For eksempel har et menneskeligt objekt tilstand (navn, køn, sovende eller ej...) og adfærd (studerer Java, går, taler...). Ethvert Java-objekt gemmer sin tilstand i felter og afslører dets adfærd gennem metoder.

Indkapsling

Dataindkapsling er at skjule interne data fra omverdenen og kun få adgang til dem gennem offentligt eksponerede metoder. Hvad betyder det? Hvilke data? Gemmer sig for hvem? Skjul betyder at begrænse direkte adgang til datamedlemmerne (felterne) i en klasse.

Sådan fungerer det i Java:

  1. Felter gøres private
  2. Hvert felt i en klasse får to specielle metoder: en getter og en setter. Getter-metoder returnerer værdien af ​​feltet. Setter-metoder giver dig mulighed for at ændre værdien af ​​feltet på en indirekte, men tilladt måde.

Eksempel på indkapsling i Java-kode:


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"; 
}
}

Hvorfor skal du bruge indkapsling?

Hovedårsagen er at gøre det nemmere at ændre din kode. Forestil dig, at du har en ansøgning til en hockeyskole, og der er en HockeyStudent- klasse med to felter, der gemmer elevens navn og alder, da han eller hun tilmeldte sig skolen. Noget som dette:

public class HockeyStudent {
public String name;
public  int ageOfEnrollment;
}
AgeOfEnrollment - feltet er offentligt, ingen getters eller settere... Denne klasse bruges af mange andre klasser, og alt var ok, indtil en udvikler besluttede, at et enkelt int-felt ikke var nok. Nogle hockeyspillere i en kohorte er næsten et år ældre end deres jævnaldrende, så det ville være mere bekvemt at opdele dem i to grupper afhængigt af den måned, de blev født. Så feltet ageOfEnrollment skal ændres til et int-array (int[][]) : det første tal er for hele år, og det andet er for måneder. Nu skal du omfaktorere al kode, der bruger Student- klassen! Men hvis din alder OfEnrollmentfelt er privat, og du har gettere og sættere, så er alt nemmere. Hvis kravet til indstilling af en elevs alder ændres, skal du blot opdatere logikken i setAgeOfEnrollment()- indstillingsmetoden, og dine klasser kan fortsætte med at bruge Student uden problemer! Dette eksempel er noget fortænkt, men jeg håber, det forklarer, hvorfor det er en god idé at bruge indkapsling.

Arv

Dette princip er lettere at forstå selv uden nogen praktisk erfaring. Gentag ikke dig selv (DRY) kunne være mottoet for arvekonceptet. Nedarvning giver dig mulighed for at oprette en underordnet klasse, der arver felterne og metoderne fra den overordnede klasse uden at omdefinere dem. Selvfølgelig kan du tilsidesætte forældreklassens felter og metoder i underklassen, men det er ikke en nødvendighed. Hvad mere er, kan du tilføje nye tilstande og adfærd i børneklassen. Forældreklasser kaldes undertiden superklasser eller basisklasser, og børneklasser er kendt som underklasser. Javas extends nøgleord bruges til at implementere princippet om arv i kode.

Sådan fungerer det i Java:

  1. Opret forældreklassen.
  2. Opret den underordnede klasse ved hjælp af nøgleordet udvider .
  3. I Child-klassens konstruktør skal du bruge metoden super(parentField1, parentField2, ...) til at indstille overordnets felter.

En konstruktør er en speciel metode, der bruges til at initialisere et nyoprettet objekt. En konstruktør har samme navn som dens klassenavn. Der er to typer konstruktører: standard (no-arg konstruktør) og parameteriseret konstruktør. En klasse skal have mindst én konstruktør (den har standardkonstruktøren, hvis ikke andre konstruktører er defineret), og den kan have mange af dem.

Hver gang du opretter et nyt objekt, ringer du til dets konstruktør. I eksemplet ovenfor gør du dette på denne linje:


Student firstStudent = new Student();

Du bruger det nye nøgleord til at kalde Student- klassens standardkonstruktør: tudent() .

Nogle regler:

  1. Én klasse kan kun have én forælder.
  2. En forældreklasse kan have mange børneklasser.
  3. En børneklasse kan have sine egne børneklasser.

Eksempel på arv i Java-kode

Lad os oprette en telefonklasse .

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...");
    }
}
Selvfølgelig er der forskellige typer telefoner, så lad os oprette to børneklasser: en til Android-telefoner og en anden til iPhones. Så tilføjer vi nogle felter og metoder, som forælderen ikke har. Og vi bruger super() til at kalde konstruktører for at initialisere de felter, som den overordnede klasse har.

Eksempel på arv i 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...");
    }
}
Så for at gentage: i Java lader arv dig udvide en klasse med underordnede klasser, der arver felterne og metoderne fra den overordnede klasse. Det er en fremragende måde at opnå kodegenanvendelighed på.

Polymorfi

Polymorfi er et objekts evne til at forvandle sig, antage forskellige former eller rettere sagt handle på forskellige måder. I Java sker polymorfi normalt, når en overordnet klassereference bruges til at henvise til et underordnet klasseobjekt.

Hvad det betyder, og hvordan det fungerer i Java:

Hvad er polymorfi i Java? Generelt betyder det, at du kan bruge det samme metodenavn til forskellige formål. Der er to typer polymorfi i Java: metodeoverstyring (dynamisk polymorfi) og metodeoverbelastning (statisk polymorfi).

Metode tilsidesætter

Du kan tilsidesætte en overordnet klasses metode i en underklasse og tvinge den til at fungere på en anden måde. Lad os oprette en musiker- forælderklasse med en play() -metode.

Eksempel på polymorfi i Java-kode


   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...");
    }
}
Forskellige musikere bruger forskellige instrumenter. Lad os oprette to børneklasser: Pianist og Violinist . Takket være polymorfi vil hver af dem udføre sin egen version af play() metoden. Når du tilsidesætter, kan du bruge @Override- annotationen, men det er ikke nødvendigt.

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...");
    }
}
Violinisten kunne være solist eller medlem af et orkester. Lad os tage det i betragtning, når vi tilsidesætter vores play() -metode.

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...");

    }
}
Lad os oprette en demo- klasse, hvor vi vil skabe tre objekter, en forekomst af hver af de tidligere oprettede klasser. Vi får se, hvilke resultater vi får.

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();
    }
}
Her er hvad vi får:

Musician said:
I am playing my instrument...
Violinist said:
I am playing the violin solo…
Pianist said:
I am playing the piano...
Enhver violinist og pianist er en musiker, men ikke enhver musiker er en violinist eller pianist. Det betyder, at du kan bruge musikerens spillemetode, hvis du ikke skal oprette en ny. Eller du kan ringe til forældrenes metode fra barnet ved hjælp af supersøgeordet . Lad os gøre det i Pianists kode:

public class Pianist extends Musician {

    String favoritePianoType;
    
    @Override
    void play(){
        super.play();
        System.out.println("I am playing the piano...");
    }
}
Lad os nu kalde vores main() -metode i Demo- klassen. Her er resultatet:

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...

Metode overbelastning

Metodeoverbelastning betyder at bruge forskellige metoder med samme navn i samme klasse. De skal være forskellige med hensyn til antallet, rækkefølgen eller typen af ​​deres parametre. Antag, at en pianist kan spille et akustisk klaver og et elektrisk klaver. For at spille en elektrisk, har musikeren brug for elektricitet. Lad os skabe to forskellige play() metoder. Den første uden parametre, for et akustisk klaver, og den anden med en parameter, der angiver, om der er strøm til rådighed.

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.");
    }
}
Forresten, du kan bruge den første play() metode i den anden play(boolean) metode på denne måde:

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.");
    }
Lad os tilføje nogle linjer til vores demo- klasse for at demonstrere vores overbelastning:

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);
    }
}
Her er resultatet:

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 ved, hvilken metode der skal bruges baseret på dens parametre og objekttypen. Det er polymorfi.

Abstraktion

Når vi definerer en klasse, forsøger vi at bygge en model af noget. Antag for eksempel, at vi skriver et videospil kaldet MyRacer med forskellige racerbiler. En spiller kan vælge en af ​​dem og så senere opdatere den eller købe en anden. Så... Hvad er en bil? En bil er en ret kompliceret ting, men hvis vi forsøger at skabe et racervideospil (i modsætning til en køresimulator), så behøver vi ikke at beskrive alle de tusindvis af gear og pakninger, den indeholder. Vi har brug for dens model, tophastighed, manøvreegenskaber, pris, farve... Og måske er det nok. Det er modellen af ​​en bil til vores spil. Antag senere i MyRacer 2, at vi beslutter at tilføje dæk, der påvirker håndteringen på vejen. Her er modellen anderledes, fordi vi har tilføjet flere detaljer. Lade' s definerer dataabstraktion som processen med kun at identificere de vigtige (eller nødvendige) egenskaber ved et objekt og ignorere alle irrelevante detaljer. Der er forskellige abstraktionsniveauer. Hvis du for eksempel er passager i en bus, skal du vide, hvordan din bus ser ud, og hvor den skal hen, men du behøver ikke vide, hvordan du kører den. Hvis du er buschauffør, behøver du ikke vide, hvordan du opretter en ny bus - du behøver kun at vide, hvordan du kører den. Men hvis du er en busproducent, skal du gå til et lavere abstraktionsniveau, fordi detaljerne i busdesignet er meget vigtige for dig. Jeg håber du forstår hvad jeg mener. du skal vide, hvordan din bus ser ud, og hvor den skal hen, men du behøver ikke vide, hvordan du kører den. Hvis du er buschauffør, behøver du ikke vide, hvordan du opretter en ny bus - du behøver kun at vide, hvordan du kører den. Men hvis du er en busproducent, skal du gå til et lavere abstraktionsniveau, fordi detaljerne i busdesignet er meget vigtige for dig. Jeg håber du forstår hvad jeg mener. du skal vide, hvordan din bus ser ud, og hvor den skal hen, men du behøver ikke vide, hvordan du kører den. Hvis du er buschauffør, behøver du ikke vide, hvordan du opretter en ny bus - du behøver kun at vide, hvordan du kører den. Men hvis du er en busproducent, skal du gå til et lavere abstraktionsniveau, fordi detaljerne i busdesignet er meget vigtige for dig. Jeg håber du forstår hvad jeg mener.

Sådan fungerer det i Java:

Lad os bygge fire abstraktionsniveauer i Java, eller rettere i OOP — fra det laveste (det mest specifikke) til det højeste (det mest abstrakte).
  1. Det laveste abstraktionsniveau er et specifikt objekt. Det er en enhed med et sæt karakteristika, der tilhører en bestemt klasse. Det har specifikke feltværdier

  2. En skabelon til at skabe objekter er en klasse. Det er en beskrivelse af et sæt objekter med lignende egenskaber og indre struktur.

  3. En abstrakt klasse er en abstrakt beskrivelse af karakteristikaene for et sæt klasser (den fungerer som en skabelon for nedarvning af andre klasser). Den har et højt abstraktionsniveau, så det er umuligt at skabe objekter direkte fra en abstrakt klasse. Kun underordnede klasser af abstrakte klasser kan bruges til at oprette objekter. En abstrakt klasse kan indeholde metoder med en implementering, men dette er ikke et krav.

  4. En grænseflade er en konstruktion af Java-programmeringssprogkonstruktionen, der kun indeholder abstrakte offentlige metoder og statiske konstantfelter (final static). Med andre ord kan hverken abstrakte klasser eller grænseflader bruges til at generere objekter.

BTW, i Java 8 eller nyere kan grænseflader ikke kun have abstrakte metoder og konstanter, men også standard og statiske metoder. I Java definerer en grænseflade en adfærd, mens en abstrakt klasse bruges til at skabe et hierarki. Én grænseflade kan implementeres af flere klasser.

Eksempel på en grænseflade i Java-kode


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

interface Vulcan {
	int angleOfPointyEars; 
	public void turnOffEmotions(boolean isOn);
	public void telepathy();
}
Du kan implementere mere end én grænseflade

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...");
}

}
For begyndere studerende dækker det alle hovedkoncepterne for objektorienteret programmering i Java. Udover de 4 vigtigste OOP-principper har Java også association, aggregering og sammensætning. Du kan kalde dem "yderligere OOP-principper". De fortjener deres egen separate artikel.
Kommentarer
TO VIEW ALL COMMENTS OR TO MAKE A COMMENT,
GO TO FULL VERSION