CodeGym/Java Blog/Willekeurig/Principes van OOP
John Squirrels
Niveau 41
San Francisco

Principes van OOP

Gepubliceerd in de groep Willekeurig
Java is een objectgeoriënteerde taal. Dit betekent dat u Java-programma's moet schrijven met behulp van een objectgeoriënteerd paradigma. En dit paradigma houdt in dat je objecten en klassen in je programma's gebruikt. Laten we voorbeelden gebruiken om te begrijpen wat klassen en objecten zijn, en hoe de basisprincipes van OOP (abstractie, overerving, polymorfisme en inkapseling) in de praktijk kunnen worden toegepast.

Wat is een voorwerp?

De wereld waarin we leven bestaat uit objecten. Als we om ons heen kijken, kunnen we zien dat we omringd zijn door huizen, bomen, auto's, meubels, borden en computers. Al deze dingen zijn objecten en elk ervan heeft een reeks specifieke kenmerken, gedragingen en doelen. We zijn gewend aan objecten en we gebruiken ze altijd voor heel specifieke doeleinden. Als we bijvoorbeeld naar ons werk moeten, gebruiken we een auto. Als we willen eten, gebruiken we gerechten. En als we willen rusten, zoeken we een comfortabele bank. Mensen zijn gewend om in termen van objecten te denken om problemen in het dagelijks leven op te lossen. Dit is een van de redenen waarom objecten worden gebruikt bij het programmeren. Deze benadering wordt objectgeoriënteerd programmeren genoemd. Laten we een voorbeeld geven. Stel je voor dat je een nieuwe telefoon hebt ontwikkeld en massaproductie wilt starten. Als ontwikkelaar van de telefoon weet je waar het voor is, hoe het werkt en wat de onderdelen zijn (behuizing, microfoon, luidspreker, draden, knoppen, enz.). Bovendien weet alleen jij hoe je deze onderdelen met elkaar verbindt. Maar je bent niet van plan om de telefoons persoonlijk te maken - je hebt een heel team van werknemers om dit te doen. Om te voorkomen dat je herhaaldelijk moet uitleggen hoe je de onderdelen van de telefoon moet verbinden, en om ervoor te zorgen dat alle telefoons op dezelfde manier zijn gemaakt, moet je voordat je ze gaat produceren een tekening maken die beschrijft hoe de telefoon is georganiseerd. In OOP noemen we zo'n beschrijving, tekening, diagram of sjabloon een klasse. Het vormt de basis voor het maken van objecten wanneer het programma wordt uitgevoerd. Een klasse is een beschrijving van objecten van een bepaald type, zoals een gemeenschappelijk sjabloon dat bestaat uit velden, methoden en een constructor. Een object is een instantie van een klasse.

Abstractie

Laten we nu eens nadenken over hoe we van een object in de echte wereld naar een object in een programma kunnen gaan. We nemen de telefoon als voorbeeld. Dit communicatiemiddel heeft een geschiedenis van meer dan 100 jaar. De moderne telefoon is een veel complexer apparaat dan zijn 19e-eeuwse voorganger. Bij het gebruik van de telefoon denken we niet na over de organisatie en de processen die erin plaatsvinden. We gebruiken gewoon de functies van de ontwikkelaars van de telefoon: knoppen of een touchscreen om een ​​telefoonnummer in te voeren en te bellen. Een van de eerste telefooninterfaces was een zwengel die moest worden gedraaid om te kunnen bellen. Dit was natuurlijk niet erg handig. Maar het vervulde zijn functie feilloos. Als je de modernste en de allereerste telefoons vergelijkt, je herkent direct de belangrijkste functies voor het laat 19e-eeuwse toestel en voor de moderne smartphone. Ze zijn de mogelijkheid om te bellen en de mogelijkheid om oproepen te ontvangen. Dit is in feite wat de telefoon tot een telefoon maakt, en niet iets anders. Nu zojuist een principe van OOP toegepast: identificeer de belangrijkste kenmerken en informatie van een object. Dit principe wordt abstractie genoemd. In OOP kan abstractie ook worden gedefinieerd als een methode om elementen van een real-world taak weer te geven als objecten in een programma. Abstractie wordt altijd geassocieerd met de generalisatie van bepaalde eigenschappen van een object, dus het belangrijkste is om zinvolle informatie te scheiden van het onbeduidende in de context van de taak die voorhanden is. Bovendien kunnen er verschillende abstractieniveaus zijn. Laten' Probeer het principe van abstractie toe te passen op onze telefoons. Om te beginnen zullen we de meest voorkomende soorten telefoons identificeren - van de allereerste telefoons tot die van vandaag. We zouden ze bijvoorbeeld kunnen weergeven in de vorm van het diagram in figuur 1. Principes van OOP - 2Met behulp van abstractie kunnen we nu de algemene informatie in deze objecthiërarchie identificeren: het algemene abstracte object (telefoon), gemeenschappelijke kenmerken van de telefoon (bijv. jaar van oprichting) en de gemeenschappelijke interface (alle telefoons kunnen oproepen ontvangen en maken). Zo ziet het eruit in 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);
}
In een programma kunnen we nieuwe typen telefoons maken door deze abstracte klasse te gebruiken en andere basisprincipes van OOP toe te passen, die we hieronder zullen onderzoeken.

Inkapseling

Met abstractie identificeren we wat gemeenschappelijk is voor alle objecten. Maar elk type telefoon is uniek en verschilt op de een of andere manier van de andere. Hoe trekken we in een programma grenzen en identificeren we deze eigenheid? Hoe zorgen we ervoor dat niemand per ongeluk of opzettelijk onze telefoon kan breken of het ene model in het andere kan proberen om te bouwen? In de echte wereld ligt het antwoord voor de hand: je moet alle onderdelen in een telefoonhoesje stoppen. Immers, als je dat niet doet - in plaats daarvan alle interne onderdelen en verbindingsdraden van de telefoon aan de buitenkant laat - zal een nieuwsgierige experimentator zeker onze telefoon willen "verbeteren". Om dergelijk geknutsel te voorkomen, wordt het principe van inkapseling gebruikt in het ontwerp en de werking van een object. Dit principe stelt dat de attributen en het gedrag van een object worden gecombineerd in één enkele klasse, de object' De interne implementatie van het object is verborgen voor de gebruiker en er is een openbare interface om met het object te werken. De taak van de programmeur is om te bepalen welke attributen en methoden van een object beschikbaar moeten zijn voor openbare toegang en welke interne implementatiedetails ontoegankelijk moeten zijn.

Inkapseling en toegangscontrole

Stel dat informatie over een telefoon (het productiejaar of het logo van de fabrikant) op de achterkant wordt gegraveerd wanneer deze wordt gemaakt. De informatie (de staat) is specifiek voor dit specifieke model. We kunnen zeggen dat de fabrikant ervoor heeft gezorgd dat deze informatie onveranderlijk was - het is onwaarschijnlijk dat iemand zou denken om de gravure te verwijderen. In de Java-wereld beschrijft een klasse de status van toekomstige objecten met behulp van velden, en hun gedrag wordt beschreven met behulp van methoden. Toegang tot de status en het gedrag van een object wordt gecontroleerd met behulp van modifiers die worden toegepast op velden en methoden: privé, beschermd, openbaar en standaard. We hebben bijvoorbeeld besloten dat het productiejaar, de naam van de fabrikant en een van de methoden interne implementatiedetails van de klasse zijn en niet kunnen worden gewijzigd door andere objecten in het programma. in code,
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");
}

 }
Met de private modifier zijn de velden en methoden van de klasse alleen toegankelijk binnen deze klasse. Dit betekent dat het onmogelijk is om van buitenaf toegang te krijgen tot privévelden, omdat de privémethoden niet kunnen worden aangeroepen. Door de toegang tot de openConnection- methode te beperken, hebben we ook de mogelijkheid om vrijelijk de interne implementatie van de methode te wijzigen, aangezien de methode gegarandeerd niet wordt gebruikt door of het werk van andere objecten onderbreekt. Om met ons object te werken, laten we de oproep- en belmethoden beschikbaar met behulp van de openbare modifier. Het aanbieden van openbare methoden voor het werken met objecten maakt ook deel uit van inkapseling, want als de toegang volledig zou worden geweigerd, zou het nutteloos worden.

Erfenis

Laten we nog eens kijken naar het diagram van telefoons. Je kunt zien dat het een hiërarchie is waarin een model alle kenmerken heeft van de modellen die zich hoger langs zijn vertakking bevinden, en enkele van zijn eigen kenmerken toevoegt. Een smartphone gebruikt bijvoorbeeld een mobiel netwerk voor communicatie (heeft de eigenschappen van een mobiele telefoon), is draadloos en draagbaar (heeft de eigenschappen van een draadloze telefoon) en kan gebeld worden en gebeld worden (heeft de eigenschappen van een telefoon). Wat we hier hebben is overerving van objecteigenschappen. Bij het programmeren betekent overerving het gebruik van bestaande klassen om nieuwe te definiëren. Laten we eens kijken naar een voorbeeld van het gebruik van overerving om een ​​smartphoneklasse te maken. Alle draadloze telefoons worden gevoed door oplaadbare batterijen, die een bepaalde levensduur hebben. Dienovereenkomstig voegen we deze eigenschap toe aan de draadloze telefoonklasse:
public abstract class CordlessPhone extends AbstractPhone {

    private int hour;

    public CordlessPhone (int year, int hour) {
        super(year);
        this.hour = hour;
    }
    }
Mobiele telefoons erven de eigenschappen van een draadloze telefoon en we implementeren de oproep- en belmethoden in deze klasse:
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);
    }
}
En tot slot hebben we de smartphoneklasse, die in tegenstelling tot klassieke mobiele telefoons een volwaardig besturingssysteem heeft. U kunt de functionaliteit van uw smartphone uitbreiden door nieuwe programma's toe te voegen die op het besturingssysteem kunnen worden uitgevoerd. In code kan de klasse als volgt worden beschreven:
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);
}

}
Zoals je kunt zien, hebben we behoorlijk wat nieuwe code gemaakt om de Smartphone- klasse te beschrijven, maar we hebben een nieuwe klasse met nieuwe functionaliteit. Dit principe van OOP maakt het mogelijk om de benodigde hoeveelheid Java-code aanzienlijk te verminderen, waardoor het leven van de programmeur gemakkelijker wordt.

Polymorfisme

Ondanks verschillen in het uiterlijk en ontwerp van verschillende soorten telefoons, kunnen we een aantal algemene gedragingen identificeren: ze kunnen allemaal gebeld worden en gebeld worden en ze hebben allemaal een vrij duidelijke en eenvoudige set bedieningselementen. In termen van programmeren laat het principe van abstractie (waar we al bekend mee zijn) ons zeggen dat telefoonobjecten een gemeenschappelijke interface hebben. Daarom kunnen mensen gemakkelijk verschillende modellen telefoons gebruiken die dezelfde bedieningselementen hebben (mechanische knoppen of een touchscreen), zonder zich te verdiepen in de technische details van het apparaat. Zo gebruik je constant een mobiele telefoon en kun je gemakkelijk bellen vanaf de vaste lijn van je vriend. Het principe van OOP dat zegt dat een programma objecten met een gemeenschappelijke interface kan gebruiken zonder enige informatie over de interne structuur van het object, wordt polymorfisme genoemd. Laten' Stel je voor dat we ons programma nodig hebben om een ​​gebruiker te beschrijven die elke telefoon kan gebruiken om een ​​andere gebruiker te bellen. Hier is hoe we het kunnen doen:
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 zullen we verschillende soorten telefoons beschrijven. Een van de eerste telefoons:
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");
    }
}
Een gewone vaste telefoon:
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");
    }
}
En tot slot een coole videofoon:
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);
    }
  }
We maken objecten in de main() methode en testen de callAnotherUser() methode:
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
Het aanroepen van dezelfde methode op het gebruikersobject levert verschillende resultaten op. Een specifieke implementatie van de methode call wordt dynamisch geselecteerd binnen de methode callAnotherUser() op basis van het specifieke type object dat wordt doorgegeven wanneer het programma wordt uitgevoerd. Dit is het belangrijkste voordeel van polymorfisme: de mogelijkheid om tijdens runtime een implementatie te kiezen. In de voorbeelden van telefoonklassen die hierboven zijn gegeven, hebben we methode-overriding gebruikt - een truc waarbij we de implementatie wijzigen van een methode die is gedefinieerd in de basisklasse zonder de handtekening van de methode te wijzigen. Dit vervangt in feite de methode: de nieuwe methode die in de subklasse is gedefinieerd, wordt aangeroepen wanneer het programma wordt uitgevoerd. Meestal, wanneer we een methode overschrijven, wordt de @Overrideannotatie wordt gebruikt. Het vertelt de compiler om de handtekeningen van de overschreven en overschrijvende methoden te controleren. Volg ten slotte deze tips om ervoor te zorgen dat uw Java-programma's consistent zijn met de principes van OOP:
  • identificeer de belangrijkste kenmerken van een object;
  • gemeenschappelijke eigenschappen en gedrag identificeren en overerving gebruiken bij het maken van klassen;
  • gebruik abstracte typen om objecten te beschrijven;
  • probeer methoden en velden die verband houden met de interne implementatie van een klasse altijd te verbergen.
Opmerkingen
  • Populair
  • Nieuw
  • Oud
Je moet ingelogd zijn om opmerkingen te kunnen maken
Deze pagina heeft nog geen opmerkingen