CodeGym/Java blogg/Slumpmässig/Principer för OOP
John Squirrels
Nivå
San Francisco

Principer för OOP

Publicerad i gruppen
Java är ett objektorienterat språk. Det betyder att du behöver skriva Java-program med hjälp av ett objektorienterat paradigm. Och detta paradigm innebär att du använder objekt och klasser i dina program. Låt oss försöka använda exempel för att förstå vad klasser och objekt är, och hur man tillämpar grundläggande OOP-principer (abstraktion, arv, polymorfism och inkapsling) i praktiken.

Vad är ett föremål?

Världen vi lever i består av föremål. När vi ser oss omkring kan vi se att vi är omgivna av hus, träd, bilar, möbler, disk och datorer. Alla dessa saker är föremål, och var och en av dem har en uppsättning specifika egenskaper, beteenden och syften. Vi är vana vid föremål, och vi använder dem alltid för mycket specifika ändamål. Om vi ​​till exempel behöver ta oss till jobbet använder vi bil. Om vi ​​vill äta använder vi disk. Och om vi vill vila hittar vi en bekväm soffa. Människor är vana vid att tänka i termer av objekt för att lösa problem i vardagen. Detta är en anledning till att objekt används i programmering. Detta tillvägagångssätt kallas objektorienterad programmering. Låt oss ge ett exempel. Föreställ dig att du har utvecklat en ny telefon och vill starta massproduktion. Som telefonens utvecklare vet du vad den är till för, hur den fungerar och vilka delar den är (kropp, mikrofon, högtalare, kablar, knappar, etc.). Dessutom är det bara du som vet hur man kopplar ihop dessa delar. Men du planerar inte att göra telefonerna personligen – du har ett helt team av arbetare för att göra detta. För att eliminera behovet av att upprepade gånger förklara hur man kopplar ihop telefonens delar, och för att säkerställa att alla telefoner är gjorda på samma sätt, innan du börjar producera dem, måste du göra en ritning som beskriver hur telefonen är organiserad. I OOP kallar vi en sådan beskrivning, ritning, diagram eller mall för en klass. Det ligger till grund för att skapa objekt när programmet körs. En klass är en beskrivning av objekt av viss typ — som en vanlig mall som består av fält, metoder och en konstruktor. Ett objekt är en instans av en klass.

Abstraktion

Låt oss nu fundera på hur vi kan flytta från ett objekt i den verkliga världen till ett objekt i ett program. Vi använder telefonen som exempel. Detta kommunikationsmedel har en historia som sträcker sig över mer än 100 år. Den moderna telefonen är en mycket mer komplex enhet än dess föregångare från 1800-talet. När vi använder telefonen tänker vi inte på dess organisation och de processer som sker inuti den. Vi använder helt enkelt de funktioner som telefonens utvecklare tillhandahåller: knappar eller en pekskärm för att ange ett telefonnummer och ringa. Ett av de första telefongränssnitten var en vev som behövde roteras för att ringa ett samtal. Naturligtvis var detta inte särskilt bekvämt. Men den fyllde sin funktion felfritt. Om du jämför de modernaste och de allra första telefonerna, du kan omedelbart identifiera de viktigaste funktionerna för enheten från det sena 1800-talet och för den moderna smartphonen. De är förmågan att ringa och förmågan att ta emot samtal. Det är faktiskt det som gör telefonen till en telefon, och inte något annat. Nu har precis tillämpat en princip för OOP: identifiera ett objekts viktigaste egenskaper och information. Denna princip kallas abstraktion. I OOP kan abstraktion också definieras som en metod för att representera delar av en verklig uppgift som objekt i ett program. Abstraktion är alltid associerad med generaliseringen av vissa egenskaper hos ett objekt, så det viktigaste är att separera meningsfull information från det obetydliga i samband med uppgiften. Dessutom kan det finnas flera abstraktionsnivåer. Låta' Försök att tillämpa abstraktionsprincipen på våra telefoner. Till att börja med kommer vi att identifiera de vanligaste typerna av telefoner — från de allra första telefonerna till dagens. Till exempel skulle vi kunna representera dem i form av diagrammet i figur 1. Principer för OOP - 2Med hjälp av abstraktion kan vi nu identifiera den allmänna informationen i denna objekthierarki: det allmänna abstrakta objektet (telefonen), telefonens vanliga egenskaper (t.ex. år då den skapades) och det gemensamma gränssnittet (alla telefoner kan ta emot och ringa samtal). Så här ser det ut i Java:
public abstract class AbstractPhone {
    private int year;

    public AbstractPhone(int year) {
        this.year = year;
    }
    public abstract void call(int outgoingNumber);
    public abstract void ring(int incomingNumber);
}
I ett program kan vi skapa nya typer av telefoner genom att använda denna abstrakta klass och tillämpa andra grundläggande principer för OOP, som vi kommer att utforska nedan.

Inkapsling

Med abstraktion identifierar vi vad som är gemensamt för alla objekt. Men varje typ av telefon är unik, på något sätt skiljer sig från de andra. Hur drar vi gränser och identifierar denna individualitet i ett program? Hur gör vi så att ingen av misstag eller avsiktligt kan bryta vår telefon eller försöka konvertera en modell till en annan? I den verkliga världen är svaret uppenbart: du måste lägga alla delar i ett telefonfodral. När allt kommer omkring, om du inte gör det – i stället lämnar alla telefonens interna delar och anslutningsledningar på utsidan – kommer någon nyfiken experimenter definitivt att vilja "förbättra" vår telefon. För att förhindra sådant mixtrande används principen om inkapsling i ett objekts design och drift. Denna princip säger att ett objekts attribut och beteende kombineras i en enda klass, objektet s interna implementering är dold för användaren och ett offentligt gränssnitt tillhandahålls för att arbeta med objektet. Programmerarens uppgift är att bestämma vilka av ett objekts attribut och metoder som ska vara tillgängliga för allmänheten och vilka som är interna implementeringsdetaljer som ska vara otillgängliga.

Inkapsling och passerkontroll

Anta att information om en telefon (dess tillverkningsår eller tillverkarens logotyp) är ingraverad på baksidan när den tillverkas. Informationen (dess tillstånd) är specifik för just denna modell. Vi kan säga att tillverkaren såg till att denna information var oföränderlig - det är osannolikt att någon skulle tänka på att ta bort gravyren. I Java-världen beskriver en klass tillståndet för framtida objekt med hjälp av fält, och deras beteende beskrivs med metoder. Åtkomst till ett objekts tillstånd och beteende styrs med hjälp av modifierare som tillämpas på fält och metoder: privat, skyddad, offentlig och standard. Till exempel beslutade vi att produktionsåret, tillverkarens namn och en av metoderna är interna implementeringsdetaljer för klassen och inte kan ändras av andra objekt i programmet. I koden,
public class SomePhone {

    private int year;
    private String company;
    public SomePhone(int year, String company) {
        this.year = year;
        this.company = company;
    }
private void openConnection(){
    // findSwitch
    // openNewConnection...
}
public void call() {
    openConnection();
    System.out.println("Calling");
}

public void ring() {
    System.out.println("Ring-ring");
}

 }
Den privata modifieraren tillåter endast åtkomst till klassens fält och metoder inom denna klass. Detta innebär att det är omöjligt att komma åt privata fält utifrån, eftersom de privata metoderna inte kan anropas. Att begränsa åtkomsten till openConnection -metoden ger oss också möjligheten att fritt ändra metodens interna implementering, eftersom metoden garanterat inte kommer att användas av eller avbryta arbetet med andra objekt. För att arbeta med vårt objekt lämnar vi samtals- och ringmetoderna tillgängliga med den offentliga modifieraren. Att tillhandahålla offentliga metoder för att arbeta med objekt är också en del av inkapslingen, eftersom om åtkomst nekades helt skulle det bli värdelöst.

Arv

Låt oss ta en ny titt på diagrammet över telefoner. Du kan se att det är en hierarki där en modell har alla funktioner i modellerna placerade högre längs sin gren och lägger till några av sina egna. Till exempel använder en smartphone ett mobilnät för kommunikation (har egenskaperna hos en mobiltelefon), är trådlös och bärbar (har egenskaperna hos en trådlös telefon) och kan ta emot och ringa samtal (har egenskaperna hos en telefon). Vad vi har här är arv av objektegenskaper. Inom programmering betyder arv att använda befintliga klasser för att definiera nya. Låt oss överväga ett exempel på hur man använder arv för att skapa en smartphoneklass. Alla trådlösa telefoner drivs av uppladdningsbara batterier, som har en viss batteritid. Följaktligen lägger vi till den här egenskapen till den trådlösa telefonklassen:
public abstract class CordlessPhone extends AbstractPhone {

    private int hour;

    public CordlessPhone (int year, int hour) {
        super(year);
        this.hour = hour;
    }
    }
Mobiltelefoner ärver egenskaperna hos en trådlös telefon, och vi implementerar samtals- och ringmetoderna i denna klass:
public class CellPhone extends CordlessPhone {
    public CellPhone(int year, int hour) {
        super(year, hour);
    }

    @Override
    public void call(int outgoingNumber) {
        System.out.println("Calling " + outgoingNumber);
    }

    @Override
    public void ring(int incomingNumber) {
        System.out.println("Incoming call from " + incomingNumber);
    }
}
Och slutligen har vi smartphoneklassen, som till skillnad från klassiska mobiltelefoner har ett fullfjädrat operativsystem. Du kan utöka din smartphones funktionalitet genom att lägga till nya program som kan köras på dess operativsystem. I kod kan klassen beskrivas enligt följande:
public class Smartphone extends CellPhone {

    private String operationSystem;

    public Smartphone(int year, int hour, String operationSystem) {
        super(year, hour);
        this.operationSystem = operationSystem;
    }
public void install(String program) {
    System.out.println("Installing " + program + " for " + operationSystem);
}

}
Som du kan se skapade vi en hel del ny kod för att beskriva Smartphone- klassen, men vi fick en ny klass med ny funktionalitet. Denna princip för OOP gör det möjligt att avsevärt minska mängden Java-kod som krävs, vilket gör livet lättare för programmeraren.

Polymorfism

Trots skillnader i utseende och design på olika typer av telefoner kan vi identifiera några vanliga beteenden: de kan alla ta emot och ringa samtal och alla har en ganska tydlig och enkel uppsättning kontroller. När det gäller programmering låter abstraktionsprincipen (som vi redan är bekanta med) oss säga att telefonobjekt har ett gemensamt gränssnitt. Det är därför människor enkelt kan använda olika modeller av telefoner som har samma kontroller (mekaniska knappar eller en pekskärm), utan att fördjupa sig i enhetens tekniska detaljer. Således använder du en mobiltelefon konstant och du kan enkelt ringa ett samtal från din väns fasta telefon. Principen för OOP som säger att ett program kan använda objekt med ett gemensamt gränssnitt utan någon information om objektets interna struktur kallas polymorfism. Låta' s föreställ dig att vi behöver vårt program för att beskriva en användare som kan använda vilken telefon som helst för att ringa en annan användare. Så här kan vi göra det:
public class User {
    private String name;

    public User(String name) {
        this.name = name;
            }

    public void callAnotherUser(int number, AbstractPhone phone){
// And here's polymorphism: using the AbstractPhone type in the code!
        phone.call(number);
    }
}
 }
Nu kommer vi att beskriva flera typer av telefoner. En av de första telefonerna:
public class ThomasEdisonPhone extends AbstractPhone {

public ThomasEdisonPhone(int year) {
    super(year);
}
    @Override
    public void call(int outgoingNumber) {
        System.out.println("Crank the handle");
        System.out.println("What number would you like to connect to?");
    }

    @Override
    public void ring(int incomingNumber) {
        System.out.println("The phone is ringing");
    }
}
En vanlig fast telefon:
public class Phone extends AbstractPhone {

    public Phone(int year) {
        super(year);
    }

    @Override
    public void call(int outgoingNumber) {
        System.out.println("Calling " + outgoingNumber);
    }

    @Override
    public void ring(int incomingNumber) {
        System.out.println("The phone is ringing");
    }
}
Och slutligen, en cool videotelefon:
public class VideoPhone extends AbstractPhone {

    public VideoPhone(int year) {
        super(year);
    }
    @Override
    public void call(int outgoingNumber) {
        System.out.println("Connecting video call to " + outgoingNumber);
    }
    @Override
    public void ring(int incomingNumber) {
        System.out.println("Incoming video call from " + incomingNumber);
    }
  }
Vi skapar objekt i main()- metoden och testar callAnotherUser()- metoden:
AbstractPhone firstPhone = new ThomasEdisonPhone(1879);
AbstractPhone phone = new Phone(1984);
AbstractPhone videoPhone=new VideoPhone(2018);
User user = new User("Jason");
user.callAnotherUser(224466, firstPhone);
// Crank the handle
// What number would you like to connect to?
user.callAnotherUser(224466, phone);
// Calling 224466
user.callAnotherUser(224466, videoPhone);
// Connecting video call to 224466
Att anropa samma metod på användarobjektet ger olika resultat. En specifik implementering av anropsmetoden väljs dynamiskt i metoden callAnotherUser() baserat på den specifika typen av objekt som skickas när programmet körs. Detta är polymorfismens främsta fördel – möjligheten att välja en implementering vid körning. I exemplen på telefonklasser som ges ovan använde vi metodöverstyrning - ett knep där vi ändrar implementeringen av en metod definierad i basklassen utan att ändra metodsignaturen. Detta ersätter i huvudsak metoden: den nya metoden som definieras i underklassen anropas när programmet körs. Vanligtvis, när vi åsidosätter en metod, visas @Overrideanteckning används. Den säger åt kompilatorn att kontrollera signaturerna för de åsidosatta och åsidosättande metoderna. Slutligen, för att säkerställa att dina Java-program är förenliga med principerna för OOP, följ dessa tips:
  • identifiera ett objekts huvudsakliga egenskaper;
  • identifiera vanliga egenskaper och beteende och använda arv när du skapar klasser;
  • använda abstrakta typer för att beskriva objekt;
  • försök att alltid dölja metoder och fält relaterade till en klasss interna implementering.
Kommentarer
  • Populär
  • Ny
  • Gammal
Du måste vara inloggad för att lämna en kommentar
Den här sidan har inga kommentarer än