Sök…


Anmärkningar

Objektorienterad programmering (OOP) är ett programmeringsparadigm baserat på begreppet "objekt", som kan innehålla data, i form av fält, ofta kända som attribut; och kod, i form av procedurer, ofta kända som metoder.

Introduktion

OOP - Objektorienterad programmering är ett mycket använt programmeringsparadigm i dessa dagar. I OOP modellerar vi verkliga problem med att använda objekt och där beteenden, för att lösa dem, programmatiskt.

Det finns fyra huvudsakliga OOP-koncept

  1. Arv
  2. polymorfism
  3. Abstraktion
  4. inkapsling

Dessa fyra koncept används tillsammans för att utveckla program i OOP.

Det finns olika språk som stöder objektorienterad programmering. De populäraste språken är

  • C ++
  • Java
  • C #
  • Python (Python är inte helt objektorienterad, men har de flesta av OOP-funktionerna i det)

OOP introduktion

Intoduction

Objektorienterad programmering (oftast kallad OOP) är ett programmeringsparadigma för att lösa problem.
Det sköna ett OO (objektorienterat) program är att vi tänker på programmet som ett gäng objekt som kommunicerar med varandra, istället för som ett sekvensiellt skript som följer specifika order.

Det finns många programmeringsspråk som stöder OOP, några av de populära är:

  • Java
  • C ++
  • c #

Python är också känt för att stödja OOP men det saknar några egenskaper.


OOP-terminologi

Den mest grundläggande termen i OOP är en klass .
En klass är i princip ett objekt som har ett tillstånd och det fungerar enligt dess tillstånd.

En annan viktig term är en instans .
Tänk på en klass som en mall som används för att skapa instanser av sig själv. Klassen är en mall och förekomsten (erna) är de konkreta föremålen.

En instans skapad från klass A kallas vanligen från 'typ A', precis som typen av 5 är int och typen av 'abcd' är en sträng .

Ett exempel på att skapa en instans som heter insance1 av typ (klass) ClassA :

Java

ClassA instance1 = new ClassA();

C ++

ClassA instance1;

eller

ClassA *instance1 = new ClassA(); # On the heap

Pytonorm

instance1 = ClassA()

Som du kan se i exemplet ovan nämndes i alla fall klassens namn och efter det fanns tomma parenteser (med undantag för C ++ där om de är tomma kan parenteserna släppas). I dessa parenteser kan vi överföra arguments till konstruktören av vår klass.

En konstruktör är en metod i en klass som kallas varje gång en instans skapas. Det kan antingen ta argument eller inte. Om programmeraren inte anger någon konstruktör för en klass de bygger skapas en tom konstruktör (en konstruktör som inte gör någonting).
På de flesta språk definieras konstruktören som en metod utan att definiera dess returtyp och med samma namn på klassen (exempel i några avsnitt).

Ett exempel på att skapa en instans med namnet b1 av typ (klass) ClassB . Konstruktören av ClassB tar ett argument av typ int :

Java

ClassA instance1 = new ClassA(5);

eller

int i = 5;
ClassA instance1 = new ClassA(i);

C ++

ClassA instance1(5);

Pytonorm

instance1 = ClassA(5)

Som ni ser är processen att skapa en instans mycket lik processen att ringa en funktion.


Funktioner vs metoder

Både funktioner och metoder är mycket lika, men i Object Oriented Design (OOD) har de var och en sin mening.
En metod är en operation som utförs i en instans av en klass. Själva metoden använder vanligen instansens tillstånd för att fungera.
Under tiden tillhör en funktion en klass och inte en specifik instans. Detta innebär att det inte använder klassens tillstånd eller data lagrade i ett exempel.

Från och med nu kommer vi att visa våra exempel bara på Java eftersom OOP är mycket tydligt på det här språket, men samma principer fungerar på alla andra OOP-språk.

I Java har en funktion ordet statisk i sin definition, som så:

// File's name is ClassA
public static int add(int a, int b) {
    return a + b;
}

Det betyder att du kan ringa det var som helst i skriptet.

// From the same file
System.out.println(add(3, 5));

// From another file in the same package (or after imported)
System.out.println(ClassA.add(3, 5));

När vi kallar funktionen från en annan fil använder vi namnet på klassen (i Java är detta också namnet på filen) den tillhör, detta ger intuitionen att funktionen tillhör klassen och inte några av dess instanser.

Däremot kan vi definiera en mehod i ClassA så:

// File's name is ClassA
public int subtract(int a, int b){
    return a - b;
}

Efter denna decleration kan vi kalla den här metoden så:

ClassA a = new ClassA();
System.out.println(a.subtract(3, 5));

Här behövde vi skapa en instans av ClassA för att kalla dess metod subtrahera. Lägg märke till att vi inte kan göra följande:

System.out.println(ClassA.subtract(3, 5));

Den här linjen kommer att producera ett kompilationsfel som klagar över, vi kallade denna icke-statiska metod utan en instans.


Använda tillståndet för en klass

Låt oss anta att vi vill implementera vår subtraheringsmetod igen, men den här gången vill vi alltid subtrahera samma antal (för varje instans). Vi kan skapa följande klass:

class ClassB {

    private int sub_amount;

    public ClassB(int sub_amount) {
        this.sub_amount = sub_amount;
    }

    public int subtract(int a) {
        return a - sub_amount;
    }

    public static void main(String[] args) {
        ClassB b = new ClassB(5);
        System.out.println(b.subtract(3)); // Ouput is -2
    }
}

När vi kör denna kod skapas en ny instans med namnet b i klass ClassB och dess konstruktör matas med värdet 5 .
Konstruktören tar nu det givna sub_mount och lagrar det som sitt eget privata fält, även kallad sub_amount (den här konventionen är mycket känd i Java för att namnge argumenten samma som fälten).
Efter det skriver vi till konsolen resultatet av att kalla metoden subtraherab med värdet 3 .

Lägg märke till att vi inte använder this. vid implementeringen av subtrahera this. som i konstruktören.
I Java behöver this bara skrivas när det finns en annan variabel med samma namn som definieras i det området. Detsamma fungerar med Pythons self .
Så när vi använder sub_amount i subtrahera, refererar vi till det privata fältet som är olika för varje klass.

Ett annat exempel att betona.
Låt oss bara ändra huvudfunktionen i koden ovan till följande:

ClassB b1 = new ClassB(1);
ClassB b2 = new ClassB(2);

System.out.println(b1.subtract(10)); // Output is 9
System.out.println(b2.subtract(10)); // Output is 8

Som vi ser är b1 och b2 oberoende och har var och en sitt eget tillstånd .


Gränssnitt och ärft

Ett gränssnitt är ett kontrakt, det definierar vilka metoder en klass kommer att ha och därför dess kapacitet. Ett gränssnitt har ingen implementering, det definierade bara vad som måste göras.
Ett exempel i Java skulle vara:

interface Printalbe {
    public void print();
}

Printalbe- gränssnittet definierar en metod som heter print men det ger inte dess implementering (ganska konstigt för Java). Varje klass som förklarar sig implementing detta gränssnitt måste tillhandahålla en implementering av dragmetoden. Till exempel:

class Person implements Printalbe {

    private String name;

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

    public void print() {
        System.out.println(name);
    }
}

Om person skulle förklara sig som implementerbar Drawable men inte tillhandahöll en implementering för att skriva ut , skulle det finnas ett sammanställningsfel och programmet skulle inte kompilera.

Arv är en term som pekar på en klass som förlänger en annan klass. Låt oss till exempel säga att vi nu har en person som har en ålder. Ett sätt att implementera en sådan person skulle vara att kopiera Personklassen och skriva en ny klass som heter AgedPerson som har samma fält och metoder men den har en annan egenskapssida.
Det här skulle vara hemskt eftersom vi kopierar hela koden bara för att lägga till en enkel funktion i vår klass.
Vi kan använda arv för att ärva från Person och därmed få alla dess funktioner och sedan förbättra dem med vår nya funktion, så:

class AgedPerson extends Person {

    private int age;

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

    public void print() {
        System.out.println("Name: " + name + ", age:" + age);
    }
}

Det finns några nya saker på gång:

  • Vi använde det sparade ordet extends att indikera att vi ärver från Person (och dess implementering till Printable , så vi behöver inte förklara att implementing Printable igen).
  • Vi använde spara ordet super att kalla personens konstruktör.
  • Vi åsidosatte utskriftsmetoden för Person med en ny.

Detta blir ganska Java-tekniskt så jag kommer inte gå djupare in i det här ämnet. Men jag kommer att nämna att det finns många extrema fall som bör läras om arv och gränssnitt innan du börjar använda dem. Vilka metoder och funktioner ärvs till exempel? Vad händer med privata / offentliga / skyddade fält när man ärver från en klass? och så vidare.

Abstrakt klass

En abstrakt klass är ganska avancerad term i OOP som beskriver en kombination av både gränssnitt och arv. Det låter dig skriva en klass som har både implementerade och oimplementerade metoder / funktioner i. I Java görs detta med hjälp av nyckelordet abstract och jag förklarar det inte mer än ett snabbt exempel:

abstract class AbstractIntStack {

    abstract public void push(int element);

    abstract public void pop();

    abstract public int top();

    final public void replaceTop(int element) {
        pop();
        push(element);
    }
}

Obs! Det final nyckelordet anger att du inte kan åsidosätta den här metoden när du ärver från den här klassen. Om en klass förklaras slutgiltig, kan ingen klass ärva från den alls.



Modified text is an extract of the original Stack Overflow Documentation
Licensierat under CC BY-SA 3.0
Inte anslutet till Stack Overflow